What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Puppeteer’s Frame.content() method to retrieve a frame’s complete HTML as a string, including its DOCTYPE:

const html = await frame.content();

If you’re starting with an iframe element, first call contentFrame() on its element handle to get the associated frame.

Get the frame’s HTML with Frame.content()

Once you have the Puppeteer Frame object you want, call:

const html = await frame.content();

The returned value is a string containing the frame’s full HTML document, including its DOCTYPE. This is the direct method for reading a frame’s complete HTML.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Get a frame from an iframe element

If you know the iframe’s selector, find its element handle, resolve the associated frame, and then read its contents:

const iframeHandle = await page.$('iframe#report');
if (!iframeHandle) {
  throw new Error('iframe#report was not found');
}

const frame = await iframeHandle.contentFrame();
const html = await frame.content();
console.log(html);

ElementHandle.contentFrame() resolves the frame associated with the element. For an HTMLIFrameElement, that associated frame exists. Check that the selector matched before calling the method so a missing iframe is handled clearly.

Complete runnable example

Install Puppeteer in your project, then run this ES module example. Replace the URL and selector with the page and iframe you need to inspect:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto('https://example.com');

  const iframeHandle = await page.$('iframe#report');
  if (!iframeHandle) {
    throw new Error('iframe#report was not found');
  }

  const frame = await iframeHandle.contentFrame();
  const html = await frame.content();
  console.log(html);
} finally {
  await browser.close();
}

If the frame is populated dynamically, wait for a condition tied to the content you need before calling content(). There is no single readiness condition that suits every page; choose one based on how that particular frame loads.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the right Puppeteer method

Need Method What it returns
The complete HTML of a frame frame.content() The frame’s full HTML string, including DOCTYPE.
A DOM expression evaluated inside a frame frame.evaluate(() => document.documentElement.outerHTML) The result of that expression in the frame’s context; use it when you specifically need a DOM expression’s result.
The page’s full HTML page.content() The page document’s HTML, not a substitute for selecting a child frame when its embedded content is the target.
One matching element inside a frame frame.$eval(selector, fn) The result of applying a function to the first matching element; it throws if no element matches.

Find the intended frame when a page has several

A page may expose multiple frames. Choose the frame that contains the content you want, then call content(). Puppeteer’s frame tree provides frame URLs and child frames, but the selector or matching rule must be chosen for the target page.

Troubleshooting

  • The iframe handle is missing: Check the selector and confirm the iframe exists before calling contentFrame(). The example throws a specific error when page.$() finds no match.
  • The HTML is empty or incomplete: If the frame fills in dynamically, wait for a page-specific condition tied to its content before reading it.
  • You got the top-level document instead of the embedded HTML: page.content() reads page HTML. Resolve and read the desired child frame instead.
  • frame.$eval() throws: It requires a matching element inside that frame. Use frame.content() for the entire frame document, or verify the selector if you need one element.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If you need a screenshot or PDF rather than the frame’s HTML string, ScreenshotNeo can return one with a single request. For example, this cURL command saves a screenshot:

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. Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. An MCP server provides screenshot tools for AI agents, and the free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000.

Sign up for 1,000 free screenshots a month, with no card required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.