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 contentFrame() to get the frame associated with an iframe element, then call frame.content() for the full document or frame.$eval() to read a specific element’s innerHTML. The example below waits for the iframe and checks that its frame is available before extracting HTML.

Get an iframe’s HTML with Puppeteer

This runnable example opens a page, finds an iframe by selector, and reads the inner HTML of its body. Replace the page URL and selector with values for your page.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com/page-with-iframe', {
      waitUntil: 'domcontentloaded',
    });

    const iframe = await page.waitForSelector('iframe#target');
    const frame = await iframe.contentFrame();
    if (!frame) throw new Error('Iframe frame is unavailable');

    await frame.waitForSelector('body');
    const bodyInnerHtml = await frame.$eval('body', el => el.innerHTML);
    console.log(bodyInnerHtml);
  } finally {
    await browser.close();
  }
})();

contentFrame() converts the iframe’s element handle into a Puppeteer Frame. The frame-scoped selector then runs inside the iframe, not against the parent page.

Choose between the whole document and one element

Get the complete iframe document

Call frame.content() when you need the full serialized document, rather than the markup inside a particular node. Puppeteer’s Frame API describes this as the full HTML contents of the frame, including the DOCTYPE.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
const fullHtml = await frame.content();
console.log(fullHtml);

Get an element’s inner HTML

Use frame.$eval(selector, callback) when you need only the children of a particular element. For example, to get the markup inside an article node:

const articleHtml = await frame.$eval('.article', el => el.innerHTML);

$eval() evaluates the callback against the first matching element. If the selector may not match, use a handle-based lookup and handle the missing element explicitly:

const article = await frame.$('.article');
const articleHtml = article
  ? await article.evaluate(el => el.innerHTML)
  : null;

if (articleHtml === null) {
  throw new Error('No .article element was found in the iframe');
}

innerHTML contains the element’s child markup; it does not include the selected element’s own opening and closing tags. If you need the entire document, use frame.content() instead.

Find the correct frame

When the page has several iframes, identify the intended one before extracting anything. You can locate its iframe element by a stable selector, or search Puppeteer’s frame list using frame metadata such as the URL or name.

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

Use an iframe selector

This is usually the clearest option when the parent document has a stable iframe ID, class, or other identifying attribute:

Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
const iframe = await page.waitForSelector('iframe#target');
if (!iframe) throw new Error('Iframe element was not found');

const frame = await iframe.contentFrame();
if (!frame) throw new Error('Iframe frame is unavailable');

const html = await frame.content();

Find the frame by URL or name

If the embedded page has a recognizable URL, inspect page.frames() and select the matching frame. This searches Puppeteer’s frame objects rather than querying an iframe element in the parent DOM.

const frame = page.frames().find(f => f.url().includes('/embedded-form'));
if (!frame) throw new Error('Embedded frame not found');

const html = await frame.content();

Use a sufficiently specific match: a broad fragment may identify the wrong frame if multiple embeds share part of a URL. Frame URLs can also change during navigation, so search after the relevant iframe has loaded.

Wait for the content you need

Finding an iframe element does not guarantee that its document has finished loading or that the target node exists. Wait for the actual content your extraction depends on. For a dynamically rendered element, wait for that selector inside the frame before evaluating it.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const iframe = await page.waitForSelector('iframe#target');
const frame = await iframe.contentFrame();
if (!frame) throw new Error('Iframe has no accessible content frame');

await frame.waitForSelector('.article');
const articleHtml = await frame.$eval('.article', el => el.innerHTML);

Choose the parent page’s navigation wait condition according to the site. domcontentloaded waits for the initial document to be parsed; it does not guarantee that an iframe’s application has finished rendering. A selector wait in the frame is a more direct check when you need a particular node.

Understand same-origin and cross-origin limits

Browser security rules still apply when Puppeteer controls the page. MDN documents that an iframe’s contentDocument is available only when the iframe and parent are same-origin; for a cross-origin frame, it returns null. The same-origin policy restricts script access to cross-origin content.

Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.

Puppeteer’s frame APIs let you target a frame, but they do not remove the browser’s security boundary or grant access to data that the browser does not expose. A frame may be visible and have a URL while its contents remain unavailable for direct DOM extraction from the parent context.

  • Same-origin embed: frame-scoped selectors and content extraction normally work once the frame is attached and its content is ready.
  • Cross-origin embed: if extraction is blocked, ask the embedded application to provide the required data through a server-side endpoint or a cooperative postMessage integration.
  • Own the embedded application: expose the specific data your parent page needs rather than relying on unrestricted access to a separate origin.

MDN describes postMessage() as a mechanism for communication between windows with different origins. It is a communication method, not a way to bypass origin checks: the embedded application must cooperate and deliberately send the data.

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

Read the rendered DOM or the original response?

frame.content() and frame.$eval() read the document as represented in the browser at the time Puppeteer runs them. If the embedded page adds or changes nodes with JavaScript, an extraction after that rendering can include those changes. If you extract too early, you may get an incomplete state or fail to find the selector.

This is different from retrieving the original HTML response body. The DOM can have been modified after the response arrived, and innerHTML returns a node’s current child markup—not a record of every script, network response, or earlier version of the page. Decide whether your task needs the browser’s current DOM or the original server response before choosing an extraction method.

Common problems and fixes

contentFrame() returns null

The iframe element handle may not currently have an associated frame. Check that the selector matched the intended iframe, that the iframe is attached, and that it has not navigated or been removed. Wait for the iframe and then resolve its frame again. Do not call frame methods until you have checked the result.

Rank #4
Sale
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient

The selector works on the page but not in the frame

frame.$eval() searches inside that frame only. A selector that matches an element in the parent document will not match an element inside the iframe, and the reverse is also true. Confirm which document contains the target and use the corresponding page or frame object.

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

The target element is missing

$eval() fails if no element matches. The frame may still be loading, the selector may be incorrect, or the application may not have rendered the content yet. Wait for a meaningful selector with frame.waitForSelector(), and use the optional-handle pattern when absence is an expected result.

The frame navigates or detaches during extraction

Navigation and detachment change the frame lifecycle; handles associated with an old document can become invalid. Puppeteer documents frame attach, navigate, and detach events. If the embed reloads, reacquire the iframe element and its frame after navigation, then wait for the new target content before reading it.

The captured HTML is empty or incomplete

Check that you are extracting the intended node and that the application has finished populating it. A frame document may exist before its client-side content is ready. Wait for a content-specific selector rather than assuming that the parent page’s navigation event means the embedded application is done.

A cross-origin frame’s DOM cannot be read

Confirm the origins involved and whether the embedded application is designed to expose data. Puppeteer does not provide a general bypass for the same-origin policy. Use a supported application API, a cooperative messaging interface, or another authorized integration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

page.content() omits the embedded document

page.content() serializes the outer page document. It does not replace frame.content() for a document inside an iframe. Resolve the target frame and call the frame method when the embedded document is what you need.

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 your goal is a visual record of a page rather than access to its DOM or an iframe’s HTML, ScreenshotNeo can return a screenshot or PDF with one GET request. It does not return iframe inner HTML, so use Puppeteer for DOM extraction.

Example cURL request (replace the URL and API key):

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 documentation for request options. Before capture, it accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server provides screenshot and PDF tools for AI agents. The free plan includes 1,000 screenshots per month with no card required; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month, with no card.

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

Frequently Asked Questions

Does Puppeteer return the iframe’s opening <iframe> tag with frame.content()?

No. It returns the embedded frame’s document. The iframe element itself belongs to the parent page and can be inspected through its element handle.

Can I get an iframe’s HTML without selecting an element?

Yes. After resolving the frame, use frame.content() for the complete serialized document.

Will ScreenshotNeo return the iframe’s DOM?

No. ScreenshotNeo returns a visual screenshot or PDF; use Puppeteer’s frame APIs when you need HTML.

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.

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