Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Use Puppeteer’s Frame API to run JavaScript inside an iframe: get the iframe’s frame with contentFrame(), then call frame.evaluate(). page.evaluate() runs in the main page’s frame, so it won’t select elements inside a separate iframe. See the Puppeteer Frame API and ElementHandle API.
Run JavaScript in an iframe by getting its Frame
This example waits for an identifiable iframe, maps its element to a Puppeteer Frame, waits for content inside it, and reads that content from the frame’s browser context:
As an Amazon Associate I earn from qualifying purchases.
const iframeElement = await page.waitForSelector('iframe#app-frame');
if (!iframeElement) throw new Error('Iframe element was not found');
const frame = await iframeElement.contentFrame();
if (!frame) throw new Error('Iframe frame was not available');
await frame.waitForSelector('#status');
const status = await frame.evaluate(() => {
return document.querySelector('#status')?.textContent?.trim() ?? null;
});
console.log(status);
contentFrame() resolves the frame associated with an iframe element. The null checks distinguish an iframe selector that did not produce an element from an element whose frame was not available. frame.waitForSelector() waits for the expected element within that frame.
Recommended Free Tools
Why page.evaluate() does not see iframe content
page.evaluate() runs in the page’s main frame. An iframe has its own Frame context, so querying for an element that exists only inside that iframe from the main frame will not find it. Call frame.evaluate() on the target frame instead. Puppeteer describes it as: “Behaves identically to Page.evaluate() except it’s run within the context of this frame.”
#1 Best Overall
Choose the target frame
Use contentFrame() when the iframe element is identifiable
If you can select the iframe reliably, contentFrame() is the direct route. Wait for the iframe element, call contentFrame(), and check that the returned frame is available before evaluating code.
Inspect page.frames() when frame properties are a better signal
When the iframe is easier to identify by its URL or another frame-level property than by a DOM selector, inspect page.frames() and choose the matching frame. You can also navigate the tree from page.mainFrame() through childFrames(). For nested iframes, each child is a separate frame: obtain the particular child frame where the target content lives before running code there.
Rank #2
Pass Node.js values into evaluate()
The function passed to evaluate() is serialized and executed in the browser context. It cannot close over variables or helper functions from Node.js lexical scope. Pass values as arguments instead:
const result = await frame.evaluate((label) => {
return `${label}: ${document.title}`;
}, 'iframe title');
console.log(result);
The browser executes the callback, and Puppeteer returns its result to Node.js. Puppeteer awaits a promise returned by the callback. Primitive results can be transferred directly, and ordinary objects are serialized; a DOM node is not returned as a live DOM object. If you need a live browser-side object, use an evaluation handle rather than expecting a returned node to remain usable in Node.js. See the Puppeteer evaluate API.
Evaluate against an element with $eval()
For a one-off operation on the first matching element in the frame, use frame.$eval(selector, fn):
const status = await frame.$eval('#status', element => {
return element.textContent?.trim() ?? null;
});
Use this when the task is confined to that element. Use frame.evaluate() when the code needs broader access to the frame’s document or multiple elements.
Rank #4
Handle navigation, loading, and nested frames
- Wait for the content you need. A frame can exist before its target element is ready. Use
frame.waitForSelector()before evaluating against that content; Puppeteer documents that it works across navigations. - Reacquire after significant navigation. Frames can attach, navigate, or detach. A reference may no longer represent the document you expect after navigation, so wait for the expected state and get the current frame again when needed.
- Target nested frames explicitly. Evaluating in a parent frame does not automatically run code in its child iframe. Locate the child frame and evaluate in that context.
Troubleshoot common failures
| Symptom | Likely cause | What to do |
|---|---|---|
contentFrame() returns null |
The iframe element is not available as a frame at that point, or the page is changing. | Confirm the selector identifies the iframe, wait for it, check the return value, and retry after the expected page state if navigation is in progress. |
| Selector works on the page but not in the iframe | The query is running in the main frame or in the wrong child frame. | Obtain the target iframe’s Frame and run waitForSelector(), $eval(), or evaluate() on that frame. |
| Evaluation runs but a Node.js variable is undefined | The browser-side callback cannot use Node.js lexical-scope variables. | Pass the value as an explicit argument to evaluate(fn, value). |
| Evaluation fails after a page transition | The frame navigated or detached, leaving the reference stale for the expected document. | Wait for the transition and reacquire the iframe’s current frame before continuing. |
| Code in a parent frame misses content in a nested iframe | The nested iframe is a separate child frame. | Traverse the frame tree or inspect page.frames(), identify the child, and evaluate there. |
Or skip the browser setup
If your goal is to capture a page rather than execute custom code inside its iframe, ScreenshotNeo can return a screenshot or PDF with one GET request. Its clean-shot workflow accepts cookie and consent banners like a visitor and removes known consent platforms, newsletter popups, and chat widgets before capture; those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. It also offers an MCP server for AI agents and includes 1,000 screenshots per month on the free plan with no card; paid plans start at $5 for 3,000.
Free tools Windows power users keep installed
One-click scans. No signup required.
Example using cURL (replace the URL with the page you want to capture):
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. Sign up for 1,000 free screenshots a month with no card.
Best Value
- Used Book in Good Condition
Frequently Asked Questions
Can Puppeteer run JavaScript inside a cross-origin iframe?
This guide establishes how to select a Puppeteer frame and evaluate code in its browser context; it does not establish detailed same-origin or sandbox behavior. Check the browser and iframe’s applicable security restrictions for your case.
Does frame.evaluate() return a DOM element I can use in Node.js?
No. Returned DOM nodes are not transferred as live DOM objects. Return serializable data, or use an evaluation handle when you need a live browser-side object.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchQuick Recap
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.




