DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
World desk8 min

How to Automate a Browser with Puppeteer: A Practical JavaScript Guide

A practical Puppeteer guide covering installation, browser launch, reliable clicks and waits, screenshots, PDFs, Firefox support, and common fixes.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To automate a browser with Puppeteer, install the package, launch a browser, open a page, navigate to a URL, interact with elements using locators, then capture or extract what you need and close the browser. Puppeteer runs headless by default and supports Chrome and Firefox; the exact browser binaries depend on your Puppeteer version.

What Puppeteer does

Puppeteer is a JavaScript library for controlling Chrome or Firefox through the Chrome DevTools Protocol (CDP) or WebDriver BiDi. It can automate browser tasks such as filling forms, clicking controls, running UI tests, capturing screenshots or PDFs, and crawling or prerendering a single-page application. It runs without a visible browser window by default, but you can configure it to show the browser. See the Puppeteer overview.

How do I automate a browser with Puppeteer?

The core workflow is launch, create a page, navigate, act on the page, collect or save the result, and close the browser. This ES module example uses the current recommended locator approach for a basic interaction:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1280, height: 800 });
  await page.goto('https://example.com');
  console.log(await page.title());
  await page.locator('a').click();
  console.log('After click:', page.url());
} finally {
  await browser.close();
}

Save it as an .mjs file and run it with Node.js in a project where puppeteer is installed. Replace the example URL and selector with the page and element your task requires. The finally block closes the browser even if a navigation or interaction throws an error.

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

Install Puppeteer

For the standard package workflow, install Puppeteer in your project with:

npm install puppeteer

The standard package manages a compatible browser for its workflow. If you use puppeteer-core, you are choosing the library without its usual bundled-browser installation workflow and need to provide a browser executable or connect to a browser yourself. Check the official installation guide for current Node.js requirements and platform setup.

Run visibly when debugging

Headless mode is the default. To see the browser while developing, launch it with headless: false:

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

Use a visible window to inspect whether the page loads, whether a selector points to the intended element, and whether a dialog or navigation changes the flow.

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

How do I click a button with Puppeteer?

Use a locator for ordinary interactions. Locators wait for an element to exist and check action readiness, including visibility, enabled state, viewport presence, and a stable bounding box before clicking. The interactions guide recommends locators for selecting and interacting with elements.

await page.locator('button[type="submit"]').click();

For a form field, use fill() to set its value:

await page.locator('input[name="email"]').fill('[email protected]');
await page.locator('button[type="submit"]').click();

Choose selectors that survive page changes

Prefer selectors that identify the intended control rather than relying on incidental layout or generated class names. When available, use accessible labels, roles, or text that reflects what a person sees. Puppeteer supports CSS and other selector approaches, including ARIA and text selectors. See the page interactions guide for locator syntax.

A selector such as button.submit-primary-7x2 may break when a site rebuilds its styles. A selector based on a stable form attribute or accessible name is usually easier to understand and maintain.

When to use lower-level APIs

waitForSelector(), ElementHandle, and page-level methods such as page.click(selector) remain available. They can be useful when you need lower-level control, but a wait for a selector does not automatically retry the action that follows it. Dispose of handles when you no longer need them so they do not accumulate and consume memory.

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

How should I wait for a page to be ready?

Wait for the state your task actually needs, not merely for the URL to change. For example, if a search submission should display results, wait for a result element before reading its text:

await page.locator('button[type="submit"]').click();
await page.locator('[data-testid="search-results"]').wait();
const resultText = await page.locator('[data-testid="search-results"]').map(el => el.textContent).wait();

Adapt the selector to the target site. Puppeteer treats URL changes—including History API changes—as navigation, which is useful for single-page applications, but a URL transition alone does not prove that the content your script needs has rendered. Avoid arbitrary fixed sleeps when a specific element or state can be awaited; a sleep may be too short on a slow response and unnecessarily long on a fast one. See the Puppeteer FAQ for its navigation definition.

How do I take a screenshot with Puppeteer?

Navigate to the page, then call page.screenshot(). This example saves a full-page PNG:

import puppeteer from 'puppeteer';

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

For just one element, take a screenshot from its locator:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.locator('main').screenshot({ path: 'main.png' });

The page API also supports other image output options. Consult the screenshot API reference for the options available in your installed version.

How do I create a PDF?

Use page.pdf() to create a PDF, for example:

await page.pdf({ path: 'page.pdf', format: 'A4' });

PDF generation uses print CSS media by default. If you need the page’s screen styles instead, switch media before generating the file:

await page.emulateMediaType('screen');
await page.pdf({ path: 'page.pdf', format: 'A4' });

Paper size, margins, landscape orientation, and other PDF options are documented in the PDF API reference.

Does Puppeteer work with Firefox?

Yes. The official FAQ says Puppeteer supports Chrome and Firefox from Puppeteer v23.0.0. Chrome uses CDP by default, while Firefox uses WebDriver BiDi by default. The project describes BiDi support as production-ready for both, while noting that feature support differs between protocols. If your workflow depends on a browser-specific feature, verify it against the protocol and browser you plan to use.

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

Browser binaries are versioned alongside Puppeteer releases. The documentation’s version 25.12.0 compatibility table maps that release to Chrome for Testing 154.0.8037.57 and Firefox 156.0.1; these are a version-specific snapshot, not permanent browser recommendations. Check the supported browsers table for the release you install before pinning browser versions.

Manage browser binaries when you need a specific version

The @puppeteer/browsers package provides CLI and programmatic browser installation and management. Its CLI can install stable Chrome for Testing:

npx @puppeteer/browsers install chrome@stable

To install a pinned version, specify that version in the install command according to the package’s current CLI syntax. On Linux or macOS, Chrome installation may require unzip; on Windows, the documented utility requirement includes tar.exe. Check the browser management documentation for current requirements and commands.

Common Puppeteer problems and fixes

The browser does not launch

  • Check installation and runtime requirements. Confirm that the Node.js version and platform dependencies match the current installation guide.
  • Check which browser you are launching. If using puppeteer-core or a separately installed browser, provide the correct executable or connection details rather than assuming a managed browser is present.
  • Check binary compatibility. Use the supported-browser table for your Puppeteer version instead of pinning a browser based on an unrelated release.

A click times out or hits the wrong element

  • Verify the selector. Inspect the live page and use a selector tied to the intended control.
  • Wait for the task’s actual state. For a dynamic page, wait for the relevant control or result element instead of adding a guessed delay.
  • Check overlays and frames. A visible banner, modal, or embedded frame can make an otherwise plausible selector target the wrong context or obstruct the control.

The URL changes but the expected content is missing

On a single-page app, navigation may be a History API or anchor change. Wait for the result element or state your next step depends on, then extract or act.

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

A PDF looks different from the browser window

PDF output uses print media by default. Call page.emulateMediaType('screen') before page.pdf() when you need screen styles.

The process hangs or consumes resources over time

Make sure every launched browser is closed in a finally block. If you retain ElementHandle objects, dispose of them when finished.

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 to capture a website rather than automate a longer browser workflow, ScreenshotNeo offers a screenshot API and MCP server. A single GET request can return a PNG, JPEG, WebP, or PDF; this cURL example saves a WebP screenshot of Stripe:

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 API documentation for parameters and response details. Cookie banners and consent prompts are accepted and removed before capture, along with known newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo’s free plan.

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

Performance and cost considerations

Browser automation requires launching or connecting to a real browser and waiting for the page and relevant state to become ready. For repeated tasks, reuse a browser process where the workflow permits, while giving each task an appropriate page and ensuring pages and browsers are closed when done. Avoid adding sleeps that do no useful synchronization; condition-based waits make runs less sensitive to network and rendering variability.

Puppeteer itself does not establish a fixed per-screenshot service cost in this workflow: your costs depend on where you run the browser and the compute resources you allocate. If your requirement is only to fetch screenshots through a service, compare the setup and billing model of an API with running browser infrastructure yourself.

Choosing Chrome or Firefox, and locators or handles

Choice Use it when Trade-off to check
Chrome with CDP Your task targets Chrome or needs Chrome-specific CDP behavior. Confirm the required feature is supported by the Chrome and Puppeteer versions you run.
Firefox with WebDriver BiDi You need to automate Firefox using Puppeteer’s supported BiDi path. Feature coverage differs by protocol; verify the APIs your workflow depends on.
Locators You want a readable selector and built-in action readiness checks for common interactions. The target still needs to identify the right element reliably.
ElementHandle and lower-level APIs You need finer-grained control over an element or an existing handle-based workflow. Manage waits and handle disposal explicitly; selector waiting does not retry a later action.

Frequently Asked Questions

Can Puppeteer run without opening a browser window?

Yes. Headless execution is the default; set headless: false in puppeteer.launch() when you need a visible browser.

Can I use Puppeteer to capture only part of a page?

Yes. Use an element locator’s screenshot() method to save a screenshot of that element.

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

Does Puppeteer support single-page applications?

Yes. URL changes caused by History API navigation can count as navigation. Wait for the content your task needs, because a URL transition alone does not ensure that content is ready.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.