Puppeteer Launch Options: Headless, Executable Path, and Browser Settings
Configure Puppeteer’s headless mode, browser binary, launch arguments, process behavior, and environment overrides with runnable examples and troubleshooting.
Puppeteer 25.12.0 launches Chrome in headless mode by default. Use headless: true for the current headless mode, headless: 'shell' for the older headless shell, and headless: false when you need a visible browser. For a custom browser binary, set executablePath and specify browser; Puppeteer guarantees compatibility only with its bundled browser. The examples below target Puppeteer 25.12.0; verify defaults when upgrading because launch options can change.
1. Install and launch Puppeteer
The standard puppeteer package downloads a compatible browser for its supported setup. This minimal program launches it, opens a page, prints the title, and closes the browser even if navigation or evaluation fails.
npm install puppeteer
// launch.js — Node.js, Puppeteer 25.12.0
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: true,
// Leave executablePath unset to use Puppeteer's bundled browser.
});
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
console.log(await page.title());
} finally {
await browser.close();
}
})().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Run it with node launch.js. Puppeteer is a Node.js library, so the runnable Puppeteer example is JavaScript. The cURL, Python, and Node.js examples in the ScreenshotNeo section provide an API-based alternative; cURL and Python do not launch Puppeteer.
2. Choose a headless mode
| Value | Behavior | When to choose it |
|---|---|---|
true |
Current headless Chrome mode; the default in the documented version. | Most automation and server-side jobs. |
'shell' |
Older headless shell mode. | When you specifically need the legacy shell behavior and have validated your workload against it. |
false |
Visible, headed browser. | Local debugging, watching interactions, or using visible-browser workflows. |
Setting devtools: true forces headless: false. If a supposedly headless job unexpectedly opens a window, check whether DevTools is enabled. See Puppeteer’s LaunchOptions API reference for the versioned definitions.
const browser = await puppeteer.launch({
headless: 'shell', // or true or false
devtools: false,
});
3. Select the browser and executable
By default, browser selects Chrome. The channel option selects a regular Chrome installation at a known system location. executablePath points directly to a browser binary. For puppeteer-core, provide either executablePath or channel, because it does not select a browser executable on your behalf.
// Use a known installed Chrome channel
const browser = await puppeteer.launch({
browser: 'chrome',
channel: 'chrome',
headless: true,
});
// Use a custom browser binary; replace this with a real path on your host
const browser = await puppeteer.launch({
browser: 'chrome',
executablePath: '/absolute/path/to/chrome',
headless: true,
});
Puppeteer documents that only its bundled browser is guaranteed to work; another binary may be incompatible. Prefer the bundled browser unless you have a concrete reason to use a system or custom build, and validate the exact browser/Puppeteer pair in the target environment. The PuppeteerNode.launch() reference covers launching and the custom-path guidance.
4. Configure arguments without breaking defaults
args adds command-line arguments to the browser process. Puppeteer normally supplies defaults that support its automation behavior. Keep them unless a specific requirement calls for changing them. ignoreDefaultArgs can be true to remove all defaults, or an array of individual arguments to filter out. The documented example filters --mute-audio:
const browser = await puppeteer.launch({
args: ['--start-maximized'],
ignoreDefaultArgs: ['--mute-audio'],
});
Removing every default argument is a broad change that can cause unexpected launch or page behavior. Review the effective arguments when debugging with defaultArgs(). Add only flags supported by the browser build you selected.
5. Set startup, process, and profile behavior
| Option | Documented behavior | Practical use |
|---|---|---|
timeout |
Startup timeout in milliseconds; default 30,000. Zero disables it. | Increase for slow starts in constrained environments; avoid disabling unless the caller has another way to detect a stuck launch. |
dumpio |
Forwards browser stdout and stderr to the Node.js process. | Turn on to inspect browser startup diagnostics. |
signal |
An abort signal closes the browser when aborted. | Connect a job cancellation or shutdown signal to browser lifetime. |
handleSIGHUP, handleSIGINT, handleSIGTERM |
All default to true. |
Control Puppeteer’s signal handling when the host process owns shutdown behavior. |
userDataDir |
Sets the browser user data directory. | Use an explicit profile directory when persistence or profile isolation is required. |
env |
Sets environment variables visible to the browser; defaults to the current process environment. | Pass a deliberate browser environment when the worker needs a controlled environment. |
const controller = new AbortController();
const browser = await puppeteer.launch({
timeout: 45_000,
dumpio: true,
signal: controller.signal,
userDataDir: '/tmp/puppeteer-profile-job-123',
env: { ...process.env },
});
// Later, when the job should be cancelled:
// controller.abort();
Use a distinct profile directory for concurrent jobs that require separate browser state. A reused profile can retain cookies and other data, which may affect repeatability. Ensure the process can write to the directory and clean up profiles according to your application’s data-retention needs.
6. Understand inherited viewport settings
LaunchOptions extends ConnectOptions. This means launch also inherits connection/page defaults. In the documented version, defaultViewport is 800 by 600; set it to null to disable the default viewport. It is a browser/page configuration default, not a Chrome command-line switch.
const browser = await puppeteer.launch({
defaultViewport: { width: 1440, height: 900 },
});
Choose dimensions that match the page behavior you need to automate. A viewport change can affect responsive layouts, lazy loading, and element positions. See ConnectOptions for inherited settings.
7. Configure defaults and environment overrides
Puppeteer configuration can set defaultBrowser and executablePath. The environment variables PUPPETEER_BROWSER and PUPPETEER_EXECUTABLE_PATH override those corresponding configuration values. The configured executable path is auto-computed by default. If the browser differs from what your launch code seems to request, inspect the configuration file and the environment inherited by the Node process.
For reference, use the official Configuration API and LaunchOptions API. Keep deployment configuration explicit and record the Puppeteer version with it so upgrades can be reviewed against current defaults.
8. A practical launch configuration
This example collects common choices while leaving the bundled browser and Puppeteer’s normal arguments intact. Change the viewport, timeout, or profile path to suit the job; do not copy the sample profile path blindly for concurrent processes.
const puppeteer = require('puppeteer');
async function captureTitle(url) {
const browser = await puppeteer.launch({
browser: 'chrome',
headless: true,
timeout: 30_000,
dumpio: false,
defaultViewport: { width: 1365, height: 768 },
});
try {
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30_000 });
return await page.title();
} finally {
await browser.close();
}
}
captureTitle('https://example.com')
.then(console.log)
.catch((error) => {
console.error(error);
process.exitCode = 1;
});
9. Troubleshooting launch problems
| Symptom | Likely cause | What to check or change |
|---|---|---|
| Browser executable not found | A custom executablePath is wrong, or puppeteer-core has no executable selection. |
Check that the path exists in the runtime environment. With puppeteer-core, set executablePath or channel. |
| Custom Chrome fails to launch or behaves differently | The binary may not match the Puppeteer version or expected browser. | Try Puppeteer’s bundled browser first. If using a custom path, specify browser and validate that combination. |
| Headless task opens a visible window | devtools: true forces headed mode, or the launch configuration sets headless: false. |
Disable DevTools and check the final options after configuration is applied. |
| Launch times out | The browser starts slowly, is unavailable, or cannot start in the environment. | Enable dumpio to see browser output and raise timeout if startup is slow but valid. Fix the launch failure before using zero to disable the timeout. |
| Unexpected launch behavior after adding flags | A flag conflicts with browser behavior or too many Puppeteer defaults were removed. | Remove custom arguments, restore defaults, then add only the needed flag. Filter a specific default rather than setting ignoreDefaultArgs: true when possible. |
| Wrong Chrome selected | A configuration value or PUPPETEER_BROWSER / PUPPETEER_EXECUTABLE_PATH override changes selection. |
Inspect process environment, Puppeteer config, and launch options together. |
| Profile lock or shared-state issue | Concurrent jobs use the same userDataDir. |
Give each concurrent browser an isolated writable profile directory. |
10. Performance, reliability, and cost
Launch configuration affects startup and repeatability more directly than page-navigation logic. Reusing a compatible bundled browser avoids custom-binary uncertainty. Avoid verbose browser I/O in normal production runs unless you need diagnostics, and set a finite startup timeout so a stalled launch does not wait forever. Use cancellation and close the browser in a finally block so errors do not leave processes running.
The research sources document option behavior, not universal launch-time benchmarks or infrastructure cost figures. Measure startup and job duration in the environment where the code runs, with the actual browser, page, and concurrency. Browser automation also requires a runtime where the selected executable and profile directories are available and writable.
11. Or skip the browser setup
If your task is to get a website screenshot rather than automate a browser session, ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request returns a PNG, JPEG, WebP, or PDF. See the API documentation for parameters and response 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}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
Cookie banners are accepted like a visitor and removed along with 60+ known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits cost nothing, with the verdict and billing status in response headers. Its MCP server lets Claude, Cursor, and other MCP clients use screenshot tools. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is on every plan. Create a free account and get 1,000 screenshots a month with no card.
12. FAQ
Does Puppeteer default to headless?
Yes. For Puppeteer 25.12.0, headless defaults to true, which means the current headless mode.
Should I set an executable path?
Only when you need a specific installed or custom browser. The bundled browser is the compatibility baseline; a custom path has weaker compatibility guarantees.
What viewport does a new page use?
The inherited defaultViewport is 800 by 600 in the documented version. Set dimensions explicitly or use null to disable that default.
What should I check after upgrading Puppeteer?
Recheck launch option names and defaults against the API docs for the version you install, especially headless behavior, browser selection, and configuration overrides.


