Free tools Windows power users keep installed
One-click scans. No signup required.
Use page.frames() to get every frame currently attached to a Puppeteer Page, then call frame.url() for each frame’s URL. If you need to preserve nested parent-child relationships, start at page.mainFrame() and recursively walk each frame’s childFrames().
List every frame and its URL
For a flat array of frames on the current page, use page.frames(). Map over the returned Frame objects to read their URLs:
As an Amazon Associate I earn from qualifying purchases.
const frames = page.frames();
console.log(frames.map(frame => frame.url()));
This includes the main frame as well as attached child frames. The result is a snapshot of frames attached when the method is called; it is not a browser-wide list of tabs. See Puppeteer’s Page API.
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 →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Keep nested frames in a tree
A flat list is convenient when you only need frame objects or URLs. To see which frames are nested under others, begin with the page’s main frame and recurse through childFrames():
#1 Best Overall
function dumpFrameTree(frame, indent = '') {
console.log(`${indent}${frame.url()}`);
for (const child of frame.childFrames()) {
dumpFrameTree(child, `${indent} `);
}
}
dumpFrameTree(page.mainFrame());
Each level is indented beneath its parent. This follows the recursive traversal pattern in Puppeteer’s official Frame API. A frame represents a DOM frame, comparable to an <iframe>; frames can contain nested frames.
Choose the right method
| Need | Use | Result |
|---|---|---|
| A quick list of frames | page.frames() |
Flat array of attached Frame objects |
| Each frame’s URL | frame.url() |
URL string for that frame; see Frame.url() |
| Parent-child nesting | page.mainFrame() and recursive frame.childFrames() |
Frame tree in parent-first order |
| Open pages in the browser | browser.pages() |
Pages (tabs), not frames; by default, non-visible pages such as background pages are omitted. See Browser.pages() |
Account for frames changing over time
Frame enumeration describes the current attached frames, and pages may change after navigation or other activity. Puppeteer documents frame-attached, frame-navigated, and frame-detached events on the parent page. If you need a later state, enumerate again; if you need to react as changes happen, track those lifecycle events using the page’s event API as documented in the Frame API.
Rank #2
Keep the scope clear: page.frames() inspects one page’s frame tree. To enumerate browser pages, use browser.pages() instead.
Troubleshooting frame lists
- The list is empty or incomplete: Check that you are querying the intended
Pageand that its content has reached the point where the frames are attached. For a dynamic page, enumerate again after the relevant navigation or track frame lifecycle events. - You see URLs but not nesting:
page.frames()returns a flat array. Traverse frompage.mainFrame()throughchildFrames()when the parent-child structure matters. - You expected other tabs: Frames belong to a page. Use
browser.pages()for the browser’s pages; its default behavior omits non-visible pages such as background pages. - A frame URL changes or a frame disappears: The frame may have navigated or detached since an earlier enumeration. Take a fresh snapshot or respond to the documented lifecycle events.
Or skip the browser setup
If your goal is to capture a page rather than inspect Puppeteer’s frame objects, ScreenshotNeo offers a one-request screenshot API. It is not a replacement for frame enumeration; use it when you need the rendered page as an image or PDF.
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. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides screenshot tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.
Sign up free for 1,000 screenshots a month with no card.
Quick Recap
Best Value
Rank #4
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.




