ScreenshotNeo

BlogHow-to

How to Check Whether a Puppeteer Frame Has Been Detached

Check a Puppeteer frame’s `detached` property for its current state, or listen for the `framedetached` event to handle a future detach.

By the ScreenshotNeo team4 October 20264 min read

To check whether a Puppeteer Frame reference has been detached, read its detached property:

if (frame.detached) {
  console.log('The frame has been detached');
}

detached is a read-only boolean. The older frame.isDetached() method is obsolete; use the property instead. For a future detach, listen for the page’s framedetached event.

1. Check a saved frame reference

This complete example gets a frame from a page, checks its current state, and avoids attempting frame work after it is detached:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com');

    const frame = page.frames().find(candidate => candidate.url().includes('embed'));
    if (!frame) {
      console.log('No matching frame is currently attached');
      return;
    }

    if (frame.detached) {
      console.log('The frame has been detached');
      return;
    }

    console.log('The frame is currently attached:', frame.url());
  } finally {
    await browser.close();
  }
})().catch(error => {
  console.error(error);
  process.exitCode = 1;
});

Replace the example URL and frame selection with the page and criteria used by your application. page.frames() returns the frames currently attached to the page, so a saved reference can be compared with that inventory as a corroborating check.

TypeScript

if (frame.detached) {
  // Do not use this Frame for further frame work.
}

The check is a snapshot: the page can change immediately afterward. Check close to the operation that needs the frame and handle errors from operations that race with navigation or removal.

2. React when a frame detaches

Register a page listener before the action that may remove or replace the iframe:

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

// Perform the action that might remove or replace the iframe only after
// registering the listener.

The event supplies the detached Frame. This is useful when you need to clean up frame-specific state or record lifecycle transitions. A listener added after the transition cannot observe that earlier event.

3. Choose the right check

Approach Use it for Limit
frame.detached Checking a known frame reference now Point-in-time state; the page can change later
page.on('framedetached', handler) Reacting to a detach transition Register before the transition
page.frames().includes(frame) Corroborating whether a reference appears in the current attached-frame inventory Inventory check rather than the direct state property

Do not use frame.parentFrame() === null as a detach test. Puppeteer documents that it is also true for the main frame, which has no parent.

4. Handle races and stale handles

A frame may detach or navigate between the property check and a later frame-scoped operation. Treat frame.detached as the state at the moment it is read, not a guarantee that the next operation will succeed. Keep the operation near the check and handle the operation’s rejection where page changes are expected.

if (!frame.detached) {
  try {
    const title = await frame.title();
    console.log(title);
  } catch (error) {
    // The frame may have navigated or detached during the operation.
    console.error('Frame operation failed:', error);
  }
}

A stale element or JavaScript handle is related but not equivalent evidence. Puppeteer disposes JavaScript handles when their associated frame navigates away or their execution context is destroyed. Check frame.detached to answer the frame-state question itself.

5. Troubleshooting

Symptom Cause Fix
frame.isDetached is not a function or deprecation guidance The old method is obsolete, or the value is not the expected Frame reference. Use frame.detached and verify how the reference was obtained.
parentFrame() returns null The frame may be the main frame, or it may be detached. Use frame.detached for the direct check.
No framedetached log appears The listener may have been registered after removal, or that action did not detach a frame. Register before the action and confirm it actually removes or replaces the iframe.
An operation fails after frame.detached was false The page changed between the check and the operation. Handle the operation error and re-check state close to use.
A handle reports a destroyed execution context Navigation or context destruction disposed the handle; this does not itself establish the frame’s current detached state. Reacquire the needed context or handle and inspect frame.detached.

6. Or skip the browser setup

If your task is to capture a page rather than manage Puppeteer frame lifecycle directly, ScreenshotNeo provides a website screenshot API and MCP server. Its single GET endpoint returns a screenshot or PDF; see the API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);

ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, with response headers indicating the page verdict and billing status. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up free for 1,000 screenshots a month, no card required.

FAQ

Is frame.detached available in TypeScript?

Yes. Read it as a boolean property on the Puppeteer Frame.

Can I tell when a frame will detach?

The framedetached event tells you when detachment occurs. Register before the action that may trigger it; it does not predict future changes.

Should I use page.frames() or frame.detached?

Use frame.detached for the direct state check. The current page.frames() inventory can corroborate whether your reference is still listed.

Does a disposed handle prove the frame detached?

No. Handle disposal can follow navigation or execution-context destruction. It is a separate signal from the frame’s detached property.

Sources