ScreenshotNeo

BlogEngineering

How the Puppeteer BrowserLauncher Works

Understand Puppeteer's BrowserLauncher, its launch options, browser binaries, headless modes, and practical setup choices.

By the ScreenshotNeo team4 October 202610 min read

Puppeteer’s BrowserLauncher is the launcher abstraction behind starting a browser. Its documented launch(options?) method returns a Promise<Browser>. You choose the browser binary, headless mode, arguments, environment, startup timeout, and process behavior through launch options. The class constructor is internal; application code should call Puppeteer’s public launch API rather than instantiate or subclass BrowserLauncher.

This guide explains the public contract and the configuration decisions that shape a launch. It does not claim a particular private sequence of internal method calls: the public API documentation describes behavior and options, while implementation details can change between Puppeteer releases. The BrowserLauncher class reference is on the next documentation branch, so check the API reference matching your installed Puppeteer version before relying on version-sensitive details.

1. The public launch contract

At a high level, your Node.js program asks Puppeteer to launch a browser, awaits a Browser object, opens pages, and eventually closes the browser. BrowserLauncher is the documented abstraction that creates and launches the browser instance. Its constructor is internal, so BrowserLauncher is not a supported third-party extension point.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
  console.log(await page.title());
} finally {
  await browser.close();
}

This is the basic workflow. The value returned by launch() is a connected Puppeteer Browser instance; use it to create pages and control the browser. Close it in a finally block so an exception during navigation or page work does not leave the child browser process running.

2. Runnable setup

For a standard Puppeteer installation, install the package and run a JavaScript file with Node.js. The standard package downloads a compatible browser build as part of its browser management workflow.

npm install puppeteer
// save as launch.mjs
import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
  headless: true,
  timeout: 30_000,
});

try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
  console.log({ title: await page.title(), url: page.url() });
} finally {
  await browser.close();
}
node launch.mjs

The documented defaults include Chrome, headless mode enabled, a 30-second startup timeout, and signal handling for SIGHUP, SIGINT, and SIGTERM. Defaults can be affected by Puppeteer configuration and environment variables. Keep installation-time browser configuration separate from per-launch options: installation determines which browser assets are available, while launch() determines how a particular process starts.

3. The key browser and binary choices

Browser family

The launcher options let you select a browser. Confirm the supported browser and option shape against the API docs for the package version in your project; not every browser option is necessarily available in every release or package.

Bundled browser, system channel, or executable path

Choice What it means When to use it
Bundled browser Use the browser build managed for Puppeteer. Best starting point for compatibility and reproducible automation.
channel Ask Puppeteer to locate a regular Chrome installation through a known system channel. Use when the host intentionally provides Chrome and you want that installation.
executablePath Point Puppeteer at an explicit browser executable. Use for a pinned or custom-installed browser, after testing that version and platform.

Puppeteer says it is only guaranteed to work with its bundled browser. The official browser-installation documentation puts compatibility testing and maintenance for custom providers on the user. The puppeteer-core launch API requires either executablePath or channel; it does not supply the usual bundled-browser default. Puppeteer’s browser-management package can install browser builds and calculate executable paths. See the installation guide and the LaunchOptions reference.

import puppeteer from 'puppeteer';

// Let Puppeteer use its managed browser.
const browser = await puppeteer.launch();
await browser.close();
import puppeteer from 'puppeteer-core';

// puppeteer-core needs an explicit browser selection.
const browser = await puppeteer.launch({
  executablePath: '/path/to/chrome',
  headless: true,
});
await browser.close();

Replace /path/to/chrome with the actual executable path on the deployment host. A path valid on a developer laptop may not exist in a container or production image.

4. Headless and headful modes

Option Behavior Considerations
headless: true Launches Chrome’s current headless mode. Use for ordinary automated browsing without a visible browser window.
headless: 'shell' Uses the separate chrome-headless-shell binary, the older headless implementation. It does not fully match regular Chrome; the guide says it may be more performant for automation that does not need the full feature set.
headless: false Launches headful Chrome. Useful for interactive debugging; the host needs a display environment or a virtual display setup.

Current Puppeteer documentation describes headless: true as the new headless mode and 'shell' as a separate binary. Older guides may describe different defaults: before Puppeteer v22, old headless was the default. Do not apply that historical default to a current project. Read the headless modes guide for the version you use.

const browser = await puppeteer.launch({ headless: 'shell' });
try {
  // Run automation that does not depend on full regular-Chrome behavior.
} finally {
  await browser.close();
}

5. LaunchOptions that affect process behavior

LaunchOptions extends connection options. The important launch controls include browser selection, command-line arguments, browser channel or executable path, headless mode, process environment, output handling, user data directory, signal handling, startup timeout, and pipe transport for Chrome. The exact accepted types and defaults are version-sensitive; use the installed release’s API reference.

Option Purpose Practical guidance
args Pass additional browser command-line arguments. Add only arguments your workload requires; record them so local and production runs match.
ignoreDefaultArgs Disable Puppeteer’s default arguments or filter selected ones. Use with care: removing defaults can break launch assumptions or browser behavior.
channel Select a regular Chrome channel found on the system. Check that the deployment image actually has that channel installed.
executablePath Specify a browser binary directly. Verify permissions, architecture, shared libraries, and browser compatibility on the target host.
headless Select current headless, headless shell, or headful operation. Choose based on behavior needed, then validate output on the target environment.
env Set the environment passed to the browser process. Pass only the variables the browser needs; avoid logging secrets from this object.
dumpio Pipe browser stdout and stderr to Node.js streams. Enable during diagnosis to expose browser startup messages; consider log volume in production.
userDataDir Choose the browser profile directory. Use an isolated writable directory per concurrent browser when state should not be shared.
handleSIGHUP, handleSIGINT, handleSIGTERM Control whether Puppeteer handles these process signals. Defaults are enabled. If changing them, ensure your application owns orderly browser cleanup.
timeout Set the browser startup timeout in milliseconds. Increase it only when startup legitimately takes longer; also inspect binary installation and host resources.
pipe Use pipe transport for Chrome rather than the usual connection transport. Choose only when your environment or connection needs call for it; check version documentation.
const browser = await puppeteer.launch({
  headless: true,
  timeout: 45_000,
  dumpio: true,
  args: ['--lang=en-US'],
  env: { ...process.env, LANG: 'en_US.UTF-8' },
});

This example inherits the Node.js environment and overrides one value. Avoid copying it blindly if the process environment contains credentials or unrelated secrets. Also avoid adding sandbox-related flags just because a deployment example elsewhere uses them: choose security settings for the actual container and threat model.

6. Configuration and browser installation

Puppeteer has configuration that affects installation and defaults, including an executable path, the default browser, and whether browser downloads are skipped. Documented environment variables can override configuration. These settings answer different questions from the per-call launch options:

  1. Install/configure: determine which browser is downloaded or where an existing binary lives.
  2. Launch: choose the binary and process behavior for this browser instance.
  3. Connect: after launch, use the returned Browser object to create and control pages.

If browser downloads are skipped, make sure the runtime image supplies a compatible browser and that the launch configuration points to it. For browser management commands and supported configuration, consult Puppeteer’s configuration guide and browser management guide.

7. A practical configuration checklist

  1. Use the managed browser first unless your deployment requires another binary.
  2. Choose current headless mode for typical automation; use headless shell only after confirming its behavior matches your workload.
  3. Set a startup timeout that reflects the host, and diagnose slow starts instead of masking them with an arbitrarily large value.
  4. Keep each concurrent browser’s profile data isolated if it writes persistent state.
  5. Turn on dumpio when you need browser process diagnostics.
  6. Keep custom arguments minimal and test any use of ignoreDefaultArgs.
  7. Close the browser in cleanup code, including error paths.
  8. Pin Puppeteer in the application lockfile and verify documentation against that installed version.

8. Reliability, performance, and cost considerations

Reliability

Browser launch can fail before a page exists if the executable is missing, incompatible, not executable, or unable to start in the host environment. Custom Chrome installations are especially sensitive to version and platform differences because Puppeteer guarantees compatibility with its bundled browser, not arbitrary installations. A reliable deployment installs the intended browser during image build, uses a known path or managed build, and includes a smoke check that launches and closes a browser in the same environment as production.

Performance

Launch overhead is distinct from navigation and page work. Reusing a browser for multiple pages can avoid repeatedly starting a process, but it also means your application must manage browser lifetime and isolate page or profile state appropriately. The documentation provides no universal speed figure. Headless shell may be more performant for narrower automation that does not need complete Chrome behavior, but measure your workload before choosing it.

Cost

Puppeteer itself is a Node.js library; operational cost comes from the machine resources, browser runtime, and any surrounding hosting or maintenance. The source material gives no benchmark or fixed hosting price. Browser processes consume resources, so concurrency, page complexity, and lifecycle management affect the infrastructure you need. Test with representative pages and load rather than relying on a generic estimate.

9. Troubleshooting launch problems

Symptom Likely cause What to do
puppeteer-core says an executable path or channel is required. puppeteer-core does not provide the bundled browser default. Pass executablePath or channel, or use the standard puppeteer package and its managed browser.
Executable path does not exist. The configured path is for another machine or the browser was not installed in the runtime image. Install the browser in that image and set the actual path, or use Puppeteer browser management.
Browser fails to start after a custom Chrome upgrade. The custom browser version may not be compatible with the installed Puppeteer release. Try the bundled browser first; otherwise pin and validate a compatible browser/Puppeteer pair.
Launch times out. Slow startup, unavailable binary, host resource pressure, or startup environment problems. Enable dumpio, confirm the executable starts in the same host, inspect available resources, and adjust timeout only when justified.
Headful mode cannot open a display. The host has no graphical display available. Use headless mode for unattended runs or provide an appropriate display environment for debugging.
Removing default arguments causes unexpected behavior. ignoreDefaultArgs removed flags Puppeteer expects. Restore defaults, then filter only the specific argument you intend to change.
Browser process remains after an error. Cleanup did not run after an exception. Put browser.close() in a finally block and handle shutdown signals consistently.
Works locally, fails in a container. Different executable, architecture, permissions, libraries, writable paths, or environment. Use the same managed browser and launch smoke check in the deployment image; compare its path and environment with local.

10. Or skip the browser setup

If the goal is to capture a website rather than manage a browser process, ScreenshotNeo provides a website screenshot API and MCP server. The one-call API returns an image or PDF, and the ScreenshotNeo documentation lists 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())));

Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. An MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots.

Create a free ScreenshotNeo account and get 1,000 screenshots a month with no card.

11. Frequently asked questions

Can application code instantiate BrowserLauncher directly?

No. Its constructor is internal, and the documented public entry point is Puppeteer’s launch API.

Does BrowserLauncher describe the entire browser automation lifecycle?

No. It covers launching. Page creation, navigation, automation, and browser shutdown happen through the returned Browser and related APIs.

Should I use a system Chrome in production?

Only if you need that deployment choice and validate the browser version, platform, and behavior your application depends on. Puppeteer guarantees compatibility with its bundled browser.

Is headless shell interchangeable with regular Chrome?

No. Puppeteer documents behavioral differences; verify that the shell mode supports the features and output your task requires.

References