To retrieve the HTML currently rendered by a page in Puppeteer, navigate to the page, wait for the content you need to appear, then call await page.content(). It returns the full document HTML, including the DOCTYPE. For a custom serialization, run document.documentElement.outerHTML with page.evaluate().
Get the rendered HTML for a full page
Install Puppeteer in your project if it is not already installed, then navigate and wait for a condition tied to the content you intend to retrieve. Replace the example URL and selector with values appropriate for the target site.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com');
// Wait for content rendered by the page's JavaScript.
await page.waitForSelector('#results');
const html = await page.content();
console.log(html);
} finally {
await browser.close();
}
page.content() returns the full HTML contents of the page, including the DOCTYPE, according to the Puppeteer Page.content() API. The example uses top-level await; use it in an ES module or place the code inside an async function. Puppeteer’s API documentation changes over time, so check the documentation for the version installed in your project.
Choose a wait condition that proves the content is ready
JavaScript-rendered content may appear after navigation completes. Choose a signal that corresponds to the data or element you need, rather than assuming navigation alone means rendering is finished.
#1 Best Overall
Wait for a specific element
When the desired content has a reliable selector, use page.waitForSelector(). It waits for a matching element to be available. For example, replace #results with a selector for the rendered content. See the Puppeteer waitForSelector() API.
Wait for an application-specific DOM condition
For a result list or status that cannot be represented by a single selector, page.waitForFunction() waits until a function evaluated in the page context returns a truthy value.
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
await page.waitForFunction(() => {
return document.querySelectorAll('.result').length > 0;
});
const html = await page.content();
This condition checks that at least one result element exists; adapt it if the page has a more precise ready state, such as a completed marker or a known minimum count. See the Puppeteer waitForFunction() API.
Wait for a response or network quiet only when it fits
page.waitForResponse()can wait for a response matching a URL or predicate. A response arriving does not prove the application has processed it and updated the DOM. See the Puppeteer waitForResponse() API.page.waitForNetworkIdle()waits for network activity to be idle for at least the configured idle time. Network quiet is not necessarily equivalent to the page being ready. Pair it with a content-specific check when possible. See the Puppeteer waitForNetworkIdle() API.
A fixed sleep can finish too early, while an unnecessarily long timeout can hide an incorrect selector or a condition that will never occur. Prefer an explicit readiness condition and handle a timeout as a sign to inspect the page and selector.
Rank #3
Retrieve custom or partial HTML
Serialize the document element yourself
Use page.evaluate() when you want to control the serialization or transform the result in the browser context:
const html = await page.evaluate(() => document.documentElement.outerHTML);
page.evaluate() runs the supplied function in the page context; if the function returns a Promise, Puppeteer awaits it. This serialization returns the document element’s outer HTML. For the full document result that includes the DOCTYPE, use page.content(). See the Puppeteer Page.evaluate() API.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
Extract one matching element
When you only need one element and its descendants, use $eval():
const html = await page.$eval('.content', element => element.outerHTML);
This returns the matched element’s outer HTML, not the whole document. If the selector does not match an element, $eval() throws. See the Puppeteer $eval() API.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsBest Value
Read HTML inside an iframe
An iframe has its own document. The main page’s page.content() does not serialize the iframe’s internal document as part of the parent document’s HTML. Find the relevant frame and call its content() or evaluate() method in that frame’s context.
const frame = page.frames().find(frame => frame.url().includes('frame-path'));
if (!frame) {
throw new Error('Target iframe was not found');
}
await frame.waitForSelector('.content');
const html = await frame.content();
Change the frame-identifying condition and selector to match the page. See the Puppeteer Frame API.
Do not confuse HTML retrieval with setting content or making a PDF
page.setContent(html)sets supplied markup as the page content; it is an input operation, not a way to read the page’s rendered HTML. See the Puppeteer Page.setContent() API.page.pdf()generates a PDF of the page; it does not return HTML. See the Puppeteer Page.pdf() API.
Troubleshoot common retrieval failures
- The HTML is missing content: Navigation may have finished before the client-side render. Wait for a selector or DOM condition representing the content, then retrieve the HTML.
waitForSelector()times out: Check that the selector exists on the page, that you are looking in the right frame, and that the element is expected to appear. If readiness is expressed by some other DOM state, usewaitForFunction()instead.$eval()throws: The selector did not match an element at evaluation time. Verify the selector and wait for the target element before calling$eval().- The expected content is inside an iframe: Retrieve the corresponding frame and use its frame-context methods; the parent document’s HTML is not the iframe document’s HTML.
- A response arrived but the HTML is unchanged: A network response alone does not confirm that the page consumed the response or rendered the desired content. Follow it with a DOM readiness check.
- Network idle never seems to be the right signal: Network activity can be unrelated to whether the target content is rendered. Prefer a selector or application-specific DOM condition when one is available.
Or skip the browser setup
For a screenshot or PDF rather than HTML markup, ScreenshotNeo offers a one-request website screenshot API and an MCP server for AI agents. It does not retrieve rendered HTML, so use Puppeteer above when HTML is the required output. For a screenshot, make a GET request with the target URL:
Quick Recap
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options and response details. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for free.
Recommended Free Tools
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.




