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.

Puppeteer is useful when a JavaScript program must operate a real browser repeatedly and predictably. It can open pages, click and type, submit forms, inspect results, save screenshots or PDFs, record performance traces, test extensions, and render dynamic single-page applications. It is not a requirement for every website: use it when browser-level automation solves a problem that ordinary HTTP requests, a browser’s developer tools, or a different test framework cannot.

What Puppeteer is

The Puppeteer documentation (version 25.12.0 displayed on September 29, 2026) defines it as “a JavaScript library which provides a high-level API to control Chrome or Firefox over the DevTools Protocol or WebDriver BiDi.” In practical terms, your JavaScript code starts or connects to a browser, tells it what a user would do, and reads or records what the browser produces.

Puppeteer runs headlessly by default, so no browser window is required on a server or in continuous integration. You can configure a visible window when developing or diagnosing a failing workflow. The browser still performs browser work: it executes JavaScript, lays out CSS, loads images, handles navigation, and exposes the resulting page to your script.

What problem does Puppeteer solve?

Many web tasks are difficult to reproduce with a simple HTTP client because the important state exists after JavaScript runs or after several user actions. Puppeteer gives those tasks a repeatable, programmable sequence.

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

Automating interaction and UI checks

A script can navigate to a URL, fill fields, press keys, click controls, wait for a result, and assert that the expected element or text appears. This is useful for regression checks on complex interfaces where a static request would never exercise the actual user flow.

Creating screenshots and PDFs

Puppeteer can capture a viewport or a full page and can print a page to PDF. Teams use these outputs for visual regression, documentation, invoices, reports, and reproducible bug evidence. The page must be allowed to finish the rendering steps you depend on; otherwise a capture can contain placeholders, unloaded images, or an intermediate state.

Investigating performance

Puppeteer can record a timeline trace while a page loads or responds to interaction. A trace helps you inspect long tasks, rendering work, network activity, and other causes of a slow experience. It is a diagnostic record, not a universal performance score: results depend on the browser, machine, network, page state, and trace settings.

Testing Chrome extensions

Extension tests can launch a browser with the extension loaded, exercise its user-facing behavior, and inspect the resulting page or background activity. This catches failures that unit tests of isolated extension functions cannot.

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

Rendering and crawling single-page applications

A crawler can wait for a client-rendered application to build its content, then collect the resulting HTML or capture an output for pre-rendered delivery. Request interception and other browser controls also support rendering and web-scraping workflows. Automation does not grant permission to collect data: check a site’s terms, robots policy, authentication rules, and applicable law before crawling.

How Puppeteer communicates with browsers

Chrome automation uses the Chrome DevTools Protocol (CDP) by default. Firefox uses WebDriver BiDi by default, and Firefox support has been available since Puppeteer 23.0.0. Puppeteer will continue supporting Chrome automation with CDP. These protocol choices matter because an API or behavior available in one browser/protocol combination may differ in another; “supports Chrome and Firefox” does not mean every feature behaves identically.

Choose the browser and protocol you will run in CI, then test the selectors, downloads, permissions, screenshots, and timing assumptions in that same combination. Avoid relying on a Chromium-only behavior if Firefox is part of your release matrix.

Installing the right package

puppeteer: managed browser download

Installing puppeteer downloads a compatible Chrome for Testing browser and headless-shell binary by default. This is the simplest choice for a project that wants Puppeteer to provide a known browser during installation.

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

puppeteer-core: you manage the browser

puppeteer-core installs the library without downloading Chrome. Use it when a browser already runs remotely, when your organization manages browser images, or when you must select a system-installed browser. Supply an explicit executable path or browser channel when your environment does not expose the expected default.

When installation scripts are blocked

Some package-manager policies disable dependency install scripts. If that prevents the automatic browser download, install the browser explicitly with npx puppeteer browsers install, or configure the package manager to allow the documented install script. Browser download sizes and package-manager defaults can change, so verify the current installation guidance for your environment.

A minimal Puppeteer workflow

The following example shows the core pattern: launch, navigate, wait for a meaningful condition, interact, and capture a result. Adapt selectors to your page rather than relying on fragile positional selectors.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({headless: true});
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', {waitUntil: 'networkidle2'});
  await page.screenshot({path: 'example.png', fullPage: true});
  await page.pdf({path: 'example.pdf', format: 'A4', printBackground: true});
} finally {
  await browser.close();
}

networkidle2 is a useful starting point, not a guarantee that an application is ready. Pages with analytics, live updates, or long-polling requests may never become truly idle. In those cases, wait for a stable selector, an application-specific readiness signal, or a bounded delay in addition to navigation.

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

When Puppeteer is the right choice

  • The workflow is browser-dependent: it needs JavaScript execution, layout, cookies, storage, permissions, or real user-like interaction.
  • You need repeatability: the same navigation and assertions must run on every pull request or scheduled job.
  • You need artifacts: screenshots, PDFs, traces, downloaded files, or rendered HTML are part of the output.
  • You need fine browser control: request interception, headers, cookies, user-agent settings, or extension loading are required.
  • Your team is comfortable with JavaScript: Puppeteer’s API and examples fit naturally into a Node.js codebase.

When you may not need Puppeteer

  • Static data retrieval: if an endpoint returns the data you need, an HTTP client is faster and simpler than launching a browser.
  • Unit-level confidence: pure functions and server code should be tested without browser startup overhead.
  • Only a one-off screenshot: a hosted screenshot API may remove browser installation and maintenance.
  • A different language or test stack is mandatory: choose a tool with first-class support for that stack instead of forcing JavaScript into the project.
  • Large distributed browser orchestration: Puppeteer itself does not provide Selenium Grid-style orchestration.

Puppeteer compared with Selenium

There is no universal replacement verdict. Puppeteer is a JavaScript library focused on direct browser control through CDP or WebDriver BiDi. Selenium provides bindings for more programming languages and includes tooling for large-scale orchestration such as Selenium Grid. Those differences should drive the decision.

Question Puppeteer is a fit when… Selenium deserves priority when…
Language Your automation is JavaScript or TypeScript. Your team needs one of Selenium’s broader language bindings.
Orchestration You run a controlled set of browser processes yourself. You need Grid-style distribution and orchestration across many sessions.
Browser behavior Your required Chrome/Firefox protocol paths are supported and tested. Your matrix depends on Selenium’s established tooling or a different protocol setup.
Maintenance You can pin compatible browser and package versions. Your organization already operates a Selenium service and test ecosystem.

Evaluate startup time, parallelism, debugging, CI images, browser versions, and the failure reports your team needs. Run a representative flow in both tools if the choice affects a large test suite.

Reliability and performance practices

Use explicit readiness conditions

Prefer a selector that proves the page is usable, such as a results container or a success message. Combine it with a timeout that fails clearly instead of allowing a test to hang indefinitely.

Keep selectors stable

Use accessible roles, labels, stable IDs, or dedicated test attributes. CSS paths based on layout depth break when a component is rearranged.

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

Isolate browser resources

Close pages and browsers in finally blocks. Reuse a browser when launching one per test is too expensive, but isolate state with separate contexts when cookies or local storage must not leak between cases.

Control nondeterminism

Freeze or seed test data where possible, wait for network and UI conditions deliberately, and collect a screenshot, console output, and trace when a failure is hard to reproduce. Do not make an unbounded sleep your only synchronization mechanism.

Budget for browser cost

Headless execution still consumes CPU, memory, disk, and network bandwidth. Full-page screenshots and PDF generation can be expensive on very long pages. Limit concurrency to what the CI runner can sustain, and measure queue time as well as browser time.

Troubleshooting common failures

“Could not find Chrome” or a missing executable

Cause: you installed puppeteer-core, the browser download script was blocked, or the executable path is wrong. Fix: install the managed browser with npx puppeteer browsers install, allow the package install script, or pass the correct executable path/channel for the browser you manage.

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

The script times out waiting for navigation

Cause: the page keeps background connections open, a request is blocked, or the site is slow. Fix: inspect console and network errors, use a suitable waitUntil value, wait for a specific ready selector, and keep a finite timeout with useful diagnostics.

A screenshot is blank or incomplete

Cause: capture happened before client rendering or lazy images finished. Fix: wait for the content selector, scroll or trigger the application’s lazy-load behavior, and verify the page at the target viewport before capturing.

Works locally but fails in CI

Cause: different browser versions, missing system libraries, sandbox restrictions, fonts, environment variables, or network access. Fix: use a reproducible browser image, log the browser version, install required dependencies, and save failure artifacts.

Firefox behaves differently from Chrome

Cause: protocol defaults and browser implementations differ. Fix: run the flow in the actual target browser, avoid undocumented browser-specific assumptions, and maintain separate assertions where behavior legitimately differs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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 simply a reliable website screenshot or PDF, ScreenshotNeo provides a hosted alternative to maintaining Puppeteer and a browser runtime. It accepts a URL and returns a PNG, JPEG, WebP, 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 documentation for parameters and response details. Equivalent calls:

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}`);
  • It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled.
  • Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Response headers identify the page verdict and whether the request was billed.
  • Its MCP server exposes take_screenshot, get_page_info, and capture_pdf 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 screenshots. Every feature is available on every plan.

Create a free ScreenshotNeo account to try the 1,000 monthly screenshots without adding a card.

Optional hosted and crawling paths

The official Puppeteer examples page names Browserless as a remote headless Chrome service and the Apify SDK as a JavaScript crawling library that manages a pool of Puppeteer browsers and related task handling. These are optional extensions, not prerequisites. Check current terms, security controls, data handling, and suitability before sending authenticated or sensitive pages to any hosted service.

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

A practical decision checklist

  1. Identify whether the task requires a real browser or can use an HTTP/API client.
  2. List the required outputs: assertions, screenshots, PDFs, traces, downloads, or rendered HTML.
  3. Choose Chrome, Firefox, or both, and test the relevant protocol path.
  4. Decide whether Puppeteer should download the browser (puppeteer) or your environment should provide it (puppeteer-core).
  5. Define stable readiness signals, selectors, timeouts, and failure artifacts.
  6. Estimate concurrency and memory needs in the environment that will run the job.
  7. Compare Selenium if you need broader language bindings or Grid-style orchestration.
  8. Use a hosted screenshot service when browser setup is the problem rather than the work itself.

Frequently Asked Questions

Is Puppeteer only for automated testing?

No. Testing is one use; Puppeteer also supports screenshots, PDFs, performance traces, extension testing, SPA rendering, request interception, and crawling workflows.

Does Puppeteer replace a browser?

No. It controls Chrome or Firefox. The `puppeteer` package downloads a compatible Chrome for Testing browser, while `puppeteer-core` expects you to provide one.

Can Puppeteer automate Firefox?

Yes, with Firefox support available since Puppeteer 23.0.0. Firefox uses WebDriver BiDi by default, so verify protocol-specific behavior rather than assuming Chrome parity.

Should I use Puppeteer or Selenium?

Choose based on language, browser/protocol requirements, and orchestration. Selenium offers more language bindings and Grid-style tooling; Puppeteer is a direct JavaScript option.

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

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.