What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Call frame.page() to get the Puppeteer Page that owns a frame:
const page = frame.page();
The method is synchronous. It returns the owning browser tab’s Page; it does not turn an iframe into an independent page. If your task is to read or interact with content inside that iframe, keep using the Frame.
What frame.page() returns
Puppeteer documents Frame.page() with the return type Page and describes the result as “The page associated with the frame.” The call is synchronous, so you do not need to await it:
const page = frame.page();
That Page represents the tab (or extension background page) that contains the frame. A Frame, by contrast, represents a document frame such as an <iframe>; frames may also be nested. See the Puppeteer Frame.page() API reference.
#1 Best Overall
Choose Page or Frame for the operation
Use the Page for tab-level work
Use frame.page() when the method you need belongs to the owning tab, or when you need to identify which page owns a frame. The page provides the frame tree through mainFrame(), frames() and, on a frame, childFrames(). See the Puppeteer Page API reference and Frame API reference.
Use the Frame for iframe content
For DOM work inside a specific iframe, call methods on that frame. For example, frame.evaluate(), frame.$eval() and frame.waitForSelector() operate in that frame’s context. Puppeteer describes Frame evaluation as behaving like Page.evaluate(), except that it runs within the selected frame’s context. See the Frame.evaluate() API reference.
const page = frame.page(); // owning tab
const titleInFrame = await frame.evaluate(() => document.title);
Getting the page does not make page-level selector shortcuts target the iframe. For example, page.$(selector) is a shortcut for page.mainFrame().$(selector), so it searches the main frame rather than an arbitrary child frame. Use the selected frame for selectors that should be scoped to that iframe. See the Page API reference.
Find a frame before getting its page
If code already has a Frame reference, call frame.page() directly. Otherwise, inspect the page’s attached frames or traverse from its main frame to child frames.
Rank #3
Inspect all attached frames
for (const frame of page.frames()) {
console.log(frame.url());
// Use frame.evaluate(...) or frame.waitForSelector(...) as needed.
}
page.frames() returns the frames attached to that page. If you need to match a frame by its element’s current name or ID, inspect its frame element rather than relying on the deprecated name() method: the name captured when a frame was created may not track later changes to the DOM name attribute. The Frame reference recommends reading the name or ID from frame.frameElement(). See the Frame API reference.
Traverse from the main frame
const main = page.mainFrame();
const children = main.childFrames();
for (const frame of children) {
console.log(frame.url(), frame.page() === page);
}
Use childFrames() when the parent-child relationship matters, including when frames are nested. If a frame has not appeared yet, the Page API includes waitForFrame() for waiting until a matching frame is attached. See the Page API reference.
Common mistakes and fixes
- Awaiting
frame.page()unnecessarily: its documented return type isPage, not a promise. Assign it directly. - Expecting the returned Page to represent only the iframe: it is the page associated with the frame. Keep the Frame reference for iframe-specific evaluation and selectors.
- Using
page.$()to search a child frame: that shortcut queries the main frame. Query the child withframe.$()or another Frame method. - Looking for a frame before it exists: wait for it with
page.waitForFrame(), then use the resulting Frame. - Depending on a frame’s old name: a name recorded when the Frame was created may be stale after the DOM changes. Read the current name or ID from
frame.frameElement().
Or skip the browser setup
If you need a screenshot rather than custom Puppeteer frame logic, ScreenshotNeo is a website screenshot API and MCP server. A single GET request can return a PNG, JPEG, WebP or PDF. For example, using cURL:
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 supported consent banners, newsletter popups and chat widgets; those steps can be turned off. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info and capture_pdf for AI agents. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.
Quick 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.

