ScreenshotNeo

BlogHow-to

List Open Pages in Puppeteer

Use `browser.pages()` to list pages across a Puppeteer browser, or `context.pages()` to inspect one browser context. See examples, caveats, and fixes.

By the ScreenshotNeo team4 October 20265 min read

Use await browser.pages() to list open pages across every browser context. To list pages in just one context, use await context.pages(). Both methods resolve to a Page[], so await the call before iterating.

const pages = await browser.pages();

for (const page of pages) {
  console.log(await page.title(), page.url());
}

Puppeteer’s Browser API documents the browser-wide method; the BrowserContext API documents the context-scoped method. A Page represents a tab or an extension background page, and a browser can have multiple pages.

Choose browser-wide or context-scoped listing

Call Scope Return value
await browser.pages() All browser contexts belonging to that browser Promise<Page[]>
await context.pages() Only the specified browser context Promise<Page[]>

A launched browser has at least its default context and may have additional contexts. Use browser-wide enumeration when you need to inspect them all. Use context enumeration when your code owns or is working within a particular user context. A popup belongs to its parent page’s context, as described in the BrowserContext reference.

Runnable example: list pages across the browser

This example launches Chromium, prints each listed page’s title and URL, and closes the browser. It requires Puppeteer installed in the project.

import puppeteer from 'puppeteer';

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

try {
  const pages = await browser.pages();
  console.log(`Found ${pages.length} page(s)`);

  for (const [index, page] of pages.entries()) {
    console.log({
      index,
      title: await page.title(),
      url: page.url(),
    });
  }
} finally {
  await browser.close();
}

Save it as list-pages.mjs and run node list-pages.mjs. If your project uses CommonJS, replace the import with const puppeteer = require('puppeteer');; the enumeration call is unchanged.

List pages in one browser context

Use context.pages() when you want to avoid mixing tabs from separate contexts. This complete example creates an isolated context, opens a page in it, and lists only that context’s pages.

import puppeteer from 'puppeteer';

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

try {
  const context = await browser.createBrowserContext();
  await context.newPage();

  const pages = await context.pages();
  for (const page of pages) {
    console.log(await page.title(), page.url());
  }
} finally {
  await browser.close();
}

Use the context object that owns the pages you care about. Calling browser.pages() in the same program instead returns pages across the browser’s contexts.

Options and visibility caveats

Both APIs document an optional includeAll?: boolean argument. The parameter is marked experimental. The ordinary listing omits non-visible page types such as background_page; the API references point to Target.page() when you need to find those. Passing true is documented to include all kinds of pages.

// Experimental: include all kinds of pages according to the API reference.
const pages = await browser.pages(true);

Check the documentation for the Puppeteer version installed in your project before relying on the experimental argument. The reviewed API references show different 25.x version labels on different pages, so version-specific behavior should be confirmed against your installed package.

Do not assume a particular order

The cited method documentation does not promise that results follow visible tab order. If your logic needs a page with a particular role, identify it by a property such as URL or title instead of relying on its array position.

const pages = await browser.pages();
const appPage = pages.find(page => page.url().startsWith('https://app.example/'));

if (!appPage) {
  throw new Error('The application page is not open');
}

Common problems and fixes

Symptom Likely cause Fix
pages is a Promise, not an array The asynchronous method was not awaited. Use const pages = await browser.pages() or await context.pages() inside an async function.
A page you expect is missing You listed a different context, or the page is a non-visible type. Use browser.pages() for all contexts. For a background page, consult the API reference’s Target.page() guidance; consider the experimental includeAll option where appropriate.
Your script selects the wrong page It assumes a documented ordering that the API references do not specify. Find the page by URL, title, or another property relevant to your task.
browser or context is undefined The variable was not initialized, is out of scope, or the browser was already closed. Launch or obtain the browser first; keep the context reference in scope and enumerate before closing the browser.
TypeScript reports that pages may be undefined An array lookup such as find() may not return a match. Check the result before using it, as in the example above.
Different behavior across Puppeteer versions The package version and the API reference version may differ, especially for experimental options. Check the installed package version and its matching API documentation; avoid depending on experimental behavior without verifying it.

Performance and reliability

Listing pages is an asynchronous discovery step. Await it once, then reuse the returned array for that inspection rather than repeatedly enumerating inside a loop. The documentation does not publish a performance benchmark or guarantee stable ordering. Page state can also change as your automation opens, closes, or navigates tabs, so enumerate at the point your workflow needs a current snapshot and handle a missing match.

Always close the browser in a finally block in scripts that launch it. This ensures cleanup even when inspecting a page fails. If a workflow manages multiple contexts, close the browser when the work is complete, or close only the context when the browser must stay running.

Or skip the browser setup

If your goal is to save a website screenshot rather than automate tabs, ScreenshotNeo provides a website screenshot API and MCP server. A single GET request returns PNG, JPEG, WebP, or PDF. Its API documentation covers the request options.

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 import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Bot checks, blank pages, failed loads, timeouts, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free account and get 1,000 screenshots a month with no card.

FAQ

Does browser.pages() include pages from every context?

Yes. It lists pages across all browser contexts belonging to that browser. Use context.pages() for one context.

Does a page object mean a browser window?

A Puppeteer Page represents a single tab or extension background page. A browser may have multiple page instances.

Can I depend on the returned array matching tab order?

The method references reviewed here do not specify an ordering guarantee. Locate pages by relevant properties instead.

How do I get a screenshot of each listed page?

Iterate over the returned Page[] and call the page’s screenshot method for each page. For a URL-to-screenshot workflow without managing browser tabs, use the ScreenshotNeo API example above.