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.

To listen for frame changes in Puppeteer, register frameattached, framenavigated, and framedetached listeners on the parent Page. Each callback receives the affected Frame, which you can inspect with methods such as url() and parentFrame().

Listen for frame lifecycle events

Register listeners before the action or navigation whose effects you need to observe. These events are dispatched on the page, including for child frames.

page.on('frameattached', frame => {
  console.log('Frame attached:', frame.url());
});

page.on('framenavigated', frame => {
  console.log('Frame navigated:', frame.url());
});

page.on('framedetached', frame => {
  console.log('Frame detached:', frame.url());
});

The callback argument is a Puppeteer Frame. This pattern is appropriate when you want to react to an ongoing stream of frame-tree changes rather than wait for just one condition.

What each event means

Event When it fires Callback value
frameattached A frame was attached to the page. The affected Frame
framenavigated A frame navigated to a new URL. The affected Frame
framedetached A frame was detached from the page. The affected Frame

These are distinct transitions: a frame can attach, navigate, and later detach. A navigation event is not an attachment event.

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

Inspect the changed frame

Use the callback’s Frame to identify its URL and place in the frame tree. The Frame API includes url(), parentFrame(), and childFrames(); a frame also has an associated page. Puppeteer treats nested frames as independent execution contexts.

page.on('framenavigated', frame => {
  const parent = frame.parentFrame();
  console.log({
    url: frame.url(),
    parentUrl: parent ? parent.url() : null,
    childCount: frame.childFrames().length,
  });
});

Use page.frames() when you need a snapshot of frames currently attached. It does not report future changes, so keep event listeners registered for ongoing monitoring.

Wait for one particular frame

If your code should proceed only when a frame matching a URL or predicate appears, use page.waitForFrame(urlOrPredicate, options). Use lifecycle listeners instead when you need to handle every attachment, navigation, or removal.

const targetFrame = await page.waitForFrame(
  frame => frame.url().includes('widget'),
  { timeout: 10000 }
);

console.log('Matched frame:', targetFrame.url());

Choose between the APIs by intent: waitForFrame() waits for a match, frames() inspects the current set, and page event listeners observe changes as they happen.

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

Handle navigation without a race

Puppeteer documents Frame.waitForNavigation() for cases where code indirectly causes a frame to navigate. History API URL changes count as navigation for this wait. When an action may trigger navigation, start the wait and action together so the navigation is not missed:

const [response] = await Promise.all([
  page.waitForNavigation(),
  page.click('a'),
]);

This is the general page-navigation pattern. If the action navigates a child frame, use the relevant frame’s navigation wait. The lifecycle event framenavigated remains useful when you want a notification rather than a one-time navigation wait.

Run code in newly created frame documents

page.evaluateOnNewDocument() addresses a related but different need: it runs in a document after creation and before that document’s scripts execute. Puppeteer says it runs when the page navigates and when a child frame attaches or navigates. Use it to install instrumentation inside each new frame context; use page lifecycle events when Node.js code needs to be notified about frame-tree changes.

Troubleshoot missing or unexpected notifications

  • No event for a change that already happened: Register listeners before the action or navigation. Events report changes from the time the listener is attached.
  • A frame’s URL change is mistaken for a new frame: Handle framenavigated separately from frameattached; they represent different lifecycle changes.
  • You need the current frames, not future updates: Read page.frames(). For future updates, subscribe to the page events.
  • A wait appears to miss navigation: Start the navigation wait and triggering action concurrently with Promise.all(), rather than awaiting the action first.
  • Code depends on a particular event API surface: Check the documentation for your installed Puppeteer version. The referenced Frame and Page class pages are version 25.12.0; the PageEvent page is labeled Next, and the evaluateOnNewDocument() page is version 25.11.0.
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 screenshot rather than monitoring iframe lifecycle events, ScreenshotNeo can return a page capture with one GET request. See the ScreenshotNeo API documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and responses say which occurred. It also offers an MCP server with screenshot and PDF tools for AI agents. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Learn about ScreenshotNeo or sign up free for 1,000 screenshots a month with no card.

Documentation and version scope

The cited Puppeteer API documentation identifies the Frame and Page class pages as version 25.12.0. The PageEvent reference is labeled Next, so verify event availability and signatures against the version installed in your project. The documented APIs here are JavaScript Puppeteer APIs.

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.