ScreenshotNeo

BlogHow-to

How to Get a Frame’s Name in Puppeteer

Use `frame.frameElement()` and evaluate the element’s current `name` or `id`. Learn how this differs from the obsolete `Frame.name()` method and how to find the right frame.

By the ScreenshotNeo team4 October 20267 min read

In current Puppeteer, get a frame’s element and read its current name or id property:

const element = await frame.frameElement();
const nameOrId = await element.evaluate(el => el.name ?? el.id);

console.log(nameOrId);

Frame.name() is obsolete in the current Puppeteer API. Its value is calculated when the frame is created and does not reflect later changes to the element attribute. Reading the frame element reads the current DOM property instead. See the official Puppeteer Frame API and Frame.name() reference.

Read a frame’s name or ID

frame.frameElement() returns the element that hosts the frame. Puppeteer’s ElementHandle.evaluate() runs the callback against that element in the page, so el.name and el.id are the element’s current DOM properties.

const frameElement = await frame.frameElement();
const nameOrId = await frameElement.evaluate(el => el.name ?? el.id);

console.log({ nameOrId, url: frame.url() });

The nullish-coalescing operator (??) uses the ID only if name is null or undefined. Since a DOM element’s name is a string, an empty name remains an empty string. If an empty name should also fall back to the ID, use el.name || el.id:

const nameOrId = await frameElement.evaluate(el => el.name || el.id);

That fallback treats an empty name as absent. Choose the behavior deliberately: ?? preserves an empty string, while || does not.

Find a frame by its current name

page.frames() returns the frames attached to the page. To locate a child frame by its current name or ID, inspect each frame element and compare its properties:

const frames = page.frames();
let match = null;

for (const frame of frames) {
  const element = await frame.frameElement();
  const identity = await element.evaluate(el => ({
    name: el.name,
    id: el.id,
  }));

  if (identity.name === 'payment' || identity.id === 'payment-frame') {
    match = frame;
    break;
  }
}

if (!match) {
  throw new Error('Could not find the payment frame');
}

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

Use the actual page’s expected name and ID in the condition. Names and IDs are not guaranteed to be unique, so if a page can contain duplicates, include additional identifying criteria such as the frame URL or the element’s other attributes.

The API reference documents page.frames() as the frames attached to the page. See the official Page.frames() reference. The guidance here concerns frames whose frame element is available; check the behavior for the main frame against the Puppeteer version installed in your project.

Why Frame.name() is not the current answer

The older frame.name() method is marked obsolete in current Puppeteer documentation. Its result is captured when the frame is created, so changing the hosting element’s name attribute later does not update that result. The frame-element approach reads the element property at evaluation time.

Approach What it returns Attribute changes Recommendation
frame.name() The frame name captured at creation Does not update after creation Obsolete; avoid for new code
frame.frameElement() then evaluate el.name or el.id The current name or ID property of the hosting element Reads the current DOM property Use when you need the current value

Deprecation guidance can change between Puppeteer releases. Check the API reference for the version your project uses when updating existing code.

Complete runnable example

This Node.js example opens a page, lists its frames, and prints each available frame element’s current name and ID. It uses Puppeteer’s documented frame APIs; install Puppeteer in your project before running it.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });

  try {
    const page = await browser.newPage();
    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });

    for (const frame of page.frames()) {
      try {
        const element = await frame.frameElement();
        const identity = await element.evaluate(el => ({
          name: el.name,
          id: el.id,
        }));

        console.log({
          name: identity.name,
          id: identity.id,
          url: frame.url(),
        });
      } catch (error) {
        console.error('Could not inspect frame:', frame.url(), error.message);
      }
    }
  } finally {
    await browser.close();
  }
})();

The per-frame try/catch lets the script continue inspecting other frames if one becomes unavailable while the page is changing. For a stable page and a known child frame, the short two-line snippet at the start is sufficient.

Edge cases and practical choices

  • Name is empty: el.name ?? el.id returns the empty string. Use el.name || el.id if empty should trigger fallback.
  • No name and no ID: Both properties are empty strings on an element without those values. Handle that explicitly if your code requires an identifier: const identity = el.name || el.id || null.
  • Attribute changes after navigation: The recommended read reflects the element property at the time evaluate() runs. If the page changes again later, read it again when you need the new value.
  • Frame detaches during inspection: A page can change while asynchronous work is in flight. Catch the error, reacquire the attached frames with page.frames(), and retry only if the operation is still relevant.
  • Duplicate names or IDs: A name or ID alone may not identify a unique frame. Compare additional properties, such as frame.url(), or inspect the frame elements before selecting one.
  • Main frame: The cited guidance gives the frame-element pattern for a frame but does not specify a main-frame exception policy. If your code may include the main frame, verify frame.frameElement() behavior with your installed Puppeteer version and handle any exception explicitly.
  • Cross-origin child content: This pattern reads the frame’s hosting element in the parent document. It does not require querying the child document to read the host element’s name or ID.

Troubleshooting

Symptom Likely cause What to do
frame.name is not a function The property is being used as a method, or the API shape/version differs. Use await frame.frameElement() and evaluate el.name or el.id. Check the installed version’s API reference.
The reported name does not change after editing the page Frame.name() returns a creation-time value. Read the hosting element’s current property with frame.frameElement() and evaluate().
The result is an empty string The element may have no name, or its name may intentionally be empty. With ??, an empty name does not fall back. Use el.name || el.id for empty-string fallback, or handle the empty value explicitly.
Evaluation fails because the frame or element is gone The page navigated, the frame detached, or its host element changed during the asynchronous operation. Catch the error, reacquire the current frames, and inspect again if needed.
The lookup selects the wrong frame More than one frame has the same name, or the lookup checks only one property. Match on multiple known properties, such as name, ID, and URL.

Performance, reliability, and cost

Reading the property requires an asynchronous Puppeteer evaluation for each inspected frame. If you are scanning many frames, fetch both name and ID in one evaluation per frame, as in the runnable example, and stop as soon as the target is found. Reacquire frame objects after page changes instead of assuming a previously collected list remains current.

This API lookup uses your own browser process and page navigation. Its runtime and resource cost depend on your environment and the page; the cited Puppeteer references report no benchmark or fixed cost. Catch detach and navigation errors where the page may change during inspection, and avoid treating a stale frame list as permanent state.

Or skip the browser setup

If your task is to capture a page screenshot rather than inspect frame metadata, ScreenshotNeo provides a website screenshot API and MCP server for developers. A single GET request returns an image or PDF. See the ScreenshotNeo 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(`ScreenshotNeo request failed: ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));

ScreenshotNeo accepts cookie or consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, with response headers indicating the page verdict and billing status. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.

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

FAQ

Does a frame’s name mean the same thing as its ID?

No. They are separate properties on the frame’s hosting element. Read the one your page uses, or check both when locating a frame.

Should I replace every use of frame.name()?

For code that needs the current host-element value, use the frame-element pattern. Confirm the behavior against your installed Puppeteer version before changing code that depends on the old method’s creation-time value.

Can I get the name without iterating over every frame?

Yes, if you already have the target Frame object. Call frame.frameElement() on it and evaluate the property directly.