To get the current page’s full HTML with Puppeteer, navigate to the page and call await page.content(). It returns the page’s serialized HTML, including the DOCTYPE. For one element, use page.$eval(); for all matching elements, use page.$$eval().
Get the full page HTML
Page.content() returns a promise containing the full HTML contents of the current page, including its DOCTYPE. The current Puppeteer API reference documents this method in version 25.12.0: Puppeteer Page.content().
As an Amazon Associate I earn from qualifying purchases.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com');
const html = await page.content();
console.log(html);
} finally {
await browser.close();
}
Save the result to a file if you need to inspect or process it later:
Free tools Windows power users keep installed
One-click scans. No signup required.
import { writeFile } from 'node:fs/promises';
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com');
const html = await page.content();
await writeFile('page.html', html, 'utf8');
} finally {
await browser.close();
}
This captures the current document representation after navigation. It is not necessarily the exact original HTTP response body: scripts may have changed the DOM, and serialization is not a byte-for-byte recovery of the network response.
#1 Best Overall
Choose the right extraction method
| What you need | Use | What it returns |
|---|---|---|
| Entire current document | await page.content() |
Full HTML, including the DOCTYPE |
| Custom DOM value or transformation | page.evaluate(() => ...) |
The value returned by your function in the page’s JavaScript context |
| One element’s markup | page.$eval(selector, callback) |
The callback result for the first matching element |
| Markup for every matching element | page.$$eval(selector, callback) |
An array of callback results |
Read the document element with evaluate
page.evaluate() runs its function in the page context, making it useful for custom DOM extraction. For example, serialize the root document element:
const html = await page.evaluate(() => document.documentElement.outerHTML);
This reads the document element’s outerHTML; unlike page.content(), that expression does not itself include the document’s DOCTYPE. Puppeteer’s guide also demonstrates extracting document.body.innerHTML: JavaScript execution.
Rank #2
Get one element’s outerHTML
Use $eval() when you know the selector and want one matching element’s serialized markup:
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →const sectionHtml = await page.$eval('main', element => element.outerHTML);
$eval() throws an error if the selector matches no element. The API reference documents that behavior: Puppeteer Page.$eval().
Get markup for all matching elements
Use $$eval() to apply a function to every matching element and return the results as an array:
const cardHtml = await page.$$eval('.card', elements =>
elements.map(element => element.outerHTML)
);
For example, cardHtml is an array of the matching cards’ markup. See the official page interactions guide for the query methods.
Rank #4
Wait for dynamic content before reading
page.goto() completing does not guarantee that every client-rendered component or asynchronously loaded section is ready for extraction. If you need a particular element, wait for the page to reach that state before reading it. Puppeteer recommends locators for element interactions because they wait for the element and relevant action preconditions.
await page.goto('https://example.com');
await page.locator('main').wait();
const mainHtml = await page.$eval('main', element => element.outerHTML);
The locator wait helps when the selector appears later than the initial document. Choose a selector that represents the content you actually need; waiting for a generic element may still be too early if the page fills it in afterward.
Best Value
- Used Book in Good Condition
Handle missing selectors safely
If an element is optional, check for it before extracting. page.$() returns a handle when it finds a match and null when it does not, so the script can avoid the exception that $eval() would raise:
const section = await page.$('main');
const sectionHtml = section
? await section.evaluate(element => element.outerHTML)
: null;
if (sectionHtml === null) {
console.log('No main element found');
}
Use this pattern when absence is a valid outcome. If the element should always exist, a clear selector failure may be more useful than silently returning null.
Current DOM versus original response HTML
Puppeteer’s page.content() and page.evaluate() expose the page’s current document representation. They are appropriate when you want the DOM after scripts have run, including client-side changes. If you need the exact original response body as received over HTTP, do not treat serialized DOM as a substitute: capture or inspect the navigation response separately. The APIs cited here describe DOM extraction, not the response-body retrieval procedure.
Recommended Free Tools
Or skip the browser setup
If your goal is a screenshot or PDF rather than extracting HTML, ScreenshotNeo offers a website screenshot API and MCP server. A single GET request can return an image or PDF. For example, with cURL:
Quick Recap
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
See the ScreenshotNeo documentation for API options. It removes supported cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are not billed. Its MCP server gives AI agents screenshot tools, and the free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up free for ScreenshotNeo.
Troubleshooting
$eval()reports that no element matched: Check that the selector is correct and that the element exists at extraction time. For delayed content, wait for the selector; if it is optional, usepage.$()and handle itsnullresult.- The HTML lacks content you see later in the browser: The page may render or update that content asynchronously. Wait for the specific element or state before calling
page.content()or evaluating markup. - The output differs from “View Source” or the original response:
page.content()serializes the current page document, which may have been changed by JavaScript. It is not a byte-for-byte copy of the original HTTP response. - The output omits the DOCTYPE: If the DOCTYPE is required, use
page.content(); serializingdocument.documentElement.outerHTMLreturns the root element’s markup.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




