Puppeteer Configuration Options Explained
Learn where Puppeteer settings belong: project configuration, browser launch, or connection. Configure downloads, Chrome, headless mode, timeouts, and network controls.
Puppeteer configuration has three layers: project configuration sets installation and runtime defaults, launch options control a browser process Puppeteer starts, and connect options control shared behavior and how Puppeteer attaches to a running browser. Choose the layer based on when and where the setting needs to apply. Configuration files are the recommended way to set defaults; applicable environment variables override them. These files and variables are ignored by puppeteer-core.
This guide covers the settings developers most often need, with runnable examples. Puppeteer options and browser requirements can change between releases, so check the API documentation for the version installed in your project: Configuration, LaunchOptions, and ConnectOptions.
1. Choose the configuration layer
| Layer | Use it for | Typical settings |
|---|---|---|
| Configuration | Installation and project-wide defaults | Browser downloads, default browser, executable path, cache directory, logging |
| LaunchOptions | One browser process that Puppeteer starts | Headless mode, arguments, profile directory, startup timeout, signal handling |
| ConnectOptions | Shared launch/connect behavior or attaching to an existing browser | Default viewport, protocol timeout, endpoint, target filtering |
Browser selection, executable paths, cache location, and download behavior belong to installation/runtime configuration or browser installation. Headless mode, process signals, launch arguments, and startup timeout belong to LaunchOptions. A setting at one layer does not automatically replace settings at another.
2. Configure installation and runtime defaults
Puppeteer searches the project tree for supported configuration filenames, including package.json, .puppeteerrc variants, and puppeteer.config variants. A JavaScript configuration file can export a configuration object. For example, create .puppeteerrc.cjs:
/** @type {import('puppeteer').Configuration} */
module.exports = {
// Keep browser downloads in the project environment's default cache.
// Set a custom path only when you have a reason to manage it.
cacheDirectory: './.cache/puppeteer',
logLevel: 'warn',
};
Configuration properties include defaultBrowser, executablePath, skipDownload, cacheDirectory, temporaryDirectory, logLevel, browser-specific settings, and experimental settings. The documented default browser cache is ~/.cache/puppeteer. Consult the Configuration API for the exact property names and values supported by your installed version.
Environment variables and precedence
When a setting has an environment-variable equivalent, the environment value takes precedence over the configuration file. Proxy settings are environment-only: HTTP_PROXY, HTTPS_PROXY, and NO_PROXY. If Puppeteer must download a browser through a proxy, the configuration guide notes that a proxy-agent optional peer dependency is needed. Use the configuration guide for the current installation details: Puppeteer configuration guide.
These configuration files and environment variables do not configure puppeteer-core. With that package, supply browser details directly where you launch or connect.
Refresh browser downloads after changing download settings
Changing a download-related configuration value does not update a browser that was already downloaded. Rerun the browser installation command:
npx puppeteer browsers install
Use the equivalent command for your package manager if needed. Starting with Puppeteer v23, the guide documents enabling the settings for multiple browsers to download more than one browser. Check the guide for version-specific instructions before relying on a particular configuration key.
3. Set options when launching a browser
LaunchOptions control a browser process started by Puppeteer. The following CommonJS script runs with the default bundled browser, headless mode, a defined viewport, and an explicit startup timeout. Save it as capture.cjs and run node capture.cjs after installing puppeteer.
const puppeteer = require('puppeteer');
async function main() {
const browser = await puppeteer.launch({
headless: true,
timeout: 30_000,
defaultViewport: { width: 1440, height: 900 },
args: [],
});
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
await browser.close();
}
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Install and use the bundled browser with:
npm install puppeteer
node capture.cjs
The standard puppeteer package downloads a specific Chrome for Testing version, which Puppeteer documents as its best-supported choice. The launch API documents headless: true, a 30-second startup timeout, devtools: false, and enabled process signal handlers as defaults. Verify defaults against the API matching your installed release.
Common launch settings
| Option | What it controls | Practical note |
|---|---|---|
browser |
Browser type to launch; Chrome is the default | Check supported values in the installed version. |
channel |
A Chrome release channel | Useful when selecting an installed channel instead of the bundled build. |
executablePath |
Path to a browser executable | With a non-bundled executable, compatibility is your responsibility. |
args |
Arguments passed to the browser | Add only arguments required by your environment; they can alter browser behavior. |
env |
Environment variables for the launched browser | Pass the minimum needed values, especially when handling credentials. |
userDataDir |
Browser profile directory | Use a separate profile for isolated jobs; avoid concurrent use of one profile. |
headless |
Headless behavior | true uses new headless mode; 'shell' selects the old headless shell mode in the current documented type. |
timeout |
How long launch waits for the browser to start | Default is 30 seconds; increase only if the environment needs more startup time. |
handleSIGINT, handleSIGTERM, handleSIGHUP |
Whether Puppeteer installs handlers for process signals | Defaults are enabled. Coordinate with the host application’s shutdown behavior. |
devtools |
Whether to open DevTools | Default is false; enabling it forces headless mode off. |
waitForInitialPage |
Whether launch waits for an initial page target | Use the API docs for the exact behavior and availability in your version. |
Using puppeteer-core or a system browser
puppeteer-core does not download or select a browser through Puppeteer’s configuration defaults. Provide executablePath or channel when launching. This example assumes a Chrome executable at the supplied path; replace it with a path available in your environment.
const puppeteer = require('puppeteer-core');
async function main() {
const browser = await puppeteer.launch({
executablePath: '/path/to/chrome',
headless: true,
});
try {
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
} finally {
await browser.close();
}
}
main().catch(console.error);
Use the Chrome for Testing build downloaded by Puppeteer when possible. Puppeteer says it only guarantees compatibility with its default browser binaries; another executable or channel requires validation against your application.
4. Connect to an existing browser
Use puppeteer.connect() when a browser is already running and exposes a supported endpoint. ConnectOptions includes shared behavior such as defaultViewport (documented default 800 by 600), protocol, and protocolTimeout (documented default 180 seconds), along with endpoint, WebSocket, and target-filtering controls. Supply the endpoint provided by your browser host; do not guess or expose it publicly.
const puppeteer = require('puppeteer');
async function main() {
const browser = await puppeteer.connect({
browserWSEndpoint: process.env.PUPPETEER_WS_ENDPOINT,
defaultViewport: { width: 1365, height: 768 },
protocolTimeout: 180_000,
});
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
console.log(await page.title());
} finally {
// Disconnect this client; the browser process is owned elsewhere.
browser.disconnect();
}
}
main().catch(console.error);
Use browser.close() when this code owns the browser and should shut it down. Use browser.disconnect() when it only attached to a browser managed by another process. Check the ConnectOptions API for all endpoint and protocol fields supported by your version.
5. Apply experimental URL allowlists and blocklists carefully
The documented allowlist and blocklist are experimental URL pattern controls. They require Chrome 149 or later and are supported only for Chrome when Puppeteer is attached to CDP targets. Do not set both together. The API warns that other mechanisms or features that omit the network service can still access the network, so these controls are an additional guardrail rather than a complete network sandbox.
For complete isolation, use container- or operating-system-level network controls. Because these options are experimental and version-sensitive, check the current ConnectOptions API before adding them to production code.
6. Configure browser installation and compatibility
Browser installation options cover the browser, build ID, cache directory, platform, and an optional expected SHA-256 hash for the downloaded archive. Providing an expected hash makes installation fail if the archive does not match; leaving it out means installation proceeds without that integrity check. See the BrowserSettings API and browser installation API for version-specific details.
Custom browser providers are not officially supported. Puppeteer tests and guarantees compatibility only for its default binaries. Treat a custom download source or executable as a compatibility choice that needs validation, including after browser or Puppeteer upgrades.
7. Troubleshoot common configuration problems
| Symptom | Likely cause | Fix |
|---|---|---|
| Configuration changes appear ignored | The project uses puppeteer-core, the file name is unsupported, or the file is outside the searched project tree. |
Confirm the package, use a supported configuration filename, and verify the file is in the project tree. For puppeteer-core, set options directly. |
| Browser does not download after changing config | Editing config does not refresh an existing browser installation. | Run npx puppeteer browsers install again. |
| Launch reports that no executable can be found | A custom path is incorrect, or puppeteer-core has neither a path nor a channel. |
Use the bundled puppeteer browser, or provide a valid executablePath or channel. |
| Browser starts but behaves differently from expected | A system/custom executable may not match the version Puppeteer supports, or launch arguments/profile state changed behavior. | Try the bundled Chrome for Testing binary, inspect args and profile settings, then validate the browser/Puppeteer pair. |
| Browser download fails behind a proxy | Proxy variables are absent or the proxy agent dependency is missing. | Set HTTP_PROXY or HTTPS_PROXY, configure NO_PROXY as appropriate, and install the documented proxy-agent optional peer dependency. |
| Launch times out | Browser startup exceeded the default 30 seconds, often due to constrained resources, a slow filesystem, or a problematic executable. | Check that the executable works and resources are available. Raise timeout only when slower startup is expected. |
| Connection or protocol operation times out | The browser endpoint is unreachable or an operation exceeded protocolTimeout. |
Confirm the WebSocket endpoint and browser ownership, then adjust the protocol timeout only for operations that legitimately take longer. |
| Headless behavior differs from older scripts | headless: true uses the new headless mode; old headless shell is a separate value. |
Use headless: 'shell' only when the old shell is specifically required and supported by your version. |
| Network filter gives a false sense of isolation | Experimental URL rules do not cover every network access path. | Use container or OS-level isolation when full network restrictions are required. |
8. Performance, reliability, and cost considerations
- Browser downloads and cache: A shared, intentionally managed cache can avoid repeated downloads in persistent build environments. Keep the cache directory writable and available to the user running Puppeteer.
- Browser profiles: Reusing a profile can preserve state, but it also carries cookies and other session data between jobs. Isolate profiles when jobs should not share state, and avoid concurrent access to the same profile directory.
- Timeouts: Keep startup and protocol timeouts aligned with the actual operation. Raising them can accommodate slow environments, but also makes failures take longer to surface.
- Browser compatibility: The bundled Chrome for Testing binary is the supported baseline. Custom binaries can introduce failures after upgrades, so validate them in the deployment environment.
- Resource use: Each browser process consumes compute and memory. Reuse a managed browser where appropriate, close pages and processes you own, and size concurrency to the host’s capacity.
- Cost: Puppeteer is software; runtime cost comes from the machine, browser execution, storage, and any browser hosting or proxy services your deployment uses. The dossier provides no benchmark or fixed operating cost, so measure resource use in your own environment.
9. Or skip the browser setup
If your goal is a website screenshot rather than browser automation, ScreenshotNeo takes a screenshot through one API request. Its options include full-page and element capture, device and viewport settings, wait conditions, custom headers and cookies, caching, PDFs, and more. See the ScreenshotNeo API documentation for parameter details.
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,
)
r.raise_for_status()
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}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
Cookie and consent banners are accepted like a visitor and removed before the shot, along with supported newsletter popups and chat widgets; each of those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. An 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 required.
10. FAQ
Should I use puppeteer or puppeteer-core?
Use puppeteer when you want Puppeteer to download its supported browser. Use puppeteer-core when your application manages the browser and can provide a path or channel.
Does headless: true mean the old headless shell?
No. The current documented type uses true for new headless mode and 'shell' for the old headless shell.
Can Puppeteer URL filtering replace a network sandbox?
No. The documented URL patterns are experimental additional controls. Use container or operating-system controls when full network isolation matters.
Where can I check whether an option exists in my installed version?
Use the official API page for the relevant layer and match it to your installed Puppeteer version. Some settings and browser requirements are version-sensitive.


