ScreenshotNeo

BlogGuides

How Puppeteer Computes a Browser Executable Path

Puppeteer’s executable path depends on its browser, cache, platform, and launch configuration. Learn how to inspect and fix the path for managed browsers, system Chrome, and puppeteer-core.

By the ScreenshotNeo team4 October 20268 min read

Puppeteer’s executablePath() returns the default executable location computed for the selected browser setup. There is no single path that applies to every installation: a managed browser’s path depends on its browser, build ID, cache directory, and platform. Configuration can override that location, while a Chrome release channel selects a system installation instead.

To diagnose a wrong or missing browser path, first identify whether the project uses puppeteer or puppeteer-core, then check the installed version, effective configuration, environment variables, and launch options. A returned path tells you where Puppeteer expects the executable; it does not by itself prove the file exists or can launch.

1. Understand the three ways Puppeteer selects an executable

Route Who chooses the browser Where Puppeteer looks Typical use
Managed browser Puppeteer’s browser installation and cache configuration The configured cache directory, for the chosen browser, build ID, and platform Default puppeteer setup
Explicit executable path Your launch option or executable-path configuration The exact path you supply Custom Chrome/Chromium install or controlled deployment image
Release channel Puppeteer’s channel lookup A known system location for that channel Use an installed stable, beta, or other supported Chrome channel

These routes answer different questions. The managed route computes a path inside Puppeteer’s download/cache arrangement. An explicit path tells launch which file to use. A channel asks Puppeteer to locate a regular system installation. Do not assume the channel search uses the managed cache.

2. Inspect the default managed-browser path

The public browser API exposes the inputs used to compute a managed executable path: browser, build ID, cache directory, and platform. Platform detection is automatic when not specified. The provider defines the executable’s relative location inside its extracted archive, so the resulting path is not a portable literal to copy between operating systems or builds.

The Puppeteer configuration reference documents the default cache directory as path.join(os.homedir(), '.cache', 'puppeteer'). PUPPETEER_CACHE_DIR can override it. The effective path also depends on which browser and build are installed. When the browser API is called with a null cache directory, the computed location can be relative to the extracted download directory, for example ./chrome-linux64/chrome.

import puppeteer from 'puppeteer';

const executable = puppeteer.executablePath();
console.log('Puppeteer executable:', executable);

This logs Puppeteer’s default computed location. It does not verify that a download completed, that the file exists, or that the executable is compatible with the host. To check existence explicitly in Node.js:

import { access } from 'node:fs/promises';
import puppeteer from 'puppeteer';

const executable = puppeteer.executablePath();
console.log(executable);
try {
  await access(executable);
  console.log('Executable exists');
} catch {
  console.error('Executable is missing or not accessible');
}

3. Check configuration and environment overrides

The configuration API marks executablePath as automatically computed by default, and documents PUPPETEER_EXECUTABLE_PATH as an override. Environment variables override applicable configuration-file values. The configuration also includes a default browser of chrome, a cache directory, and browser download settings.

Check the values in the same process and deployment environment that runs Puppeteer. A shell value on your laptop may not be present in a container, CI worker, serverless function, or service manager.

node --input-type=module -e "import puppeteer from 'puppeteer'; console.log({version: puppeteer.version, executable: puppeteer.executablePath(), env: {PUPPETEER_EXECUTABLE_PATH: process.env.PUPPETEER_EXECUTABLE_PATH, PUPPETEER_CACHE_DIR: process.env.PUPPETEER_CACHE_DIR, PUPPETEER_BROWSER: process.env.PUPPETEER_BROWSER}})"

Also inspect the project’s Puppeteer configuration file and the install command’s environment. If browser download was skipped during installation, the package may be present while the expected browser binary is absent.

4. Explicit path and Chrome channel

Use an explicit executable path

Pass executablePath to launch() when you intentionally manage the browser yourself. This takes responsibility for the path and browser compatibility out of Puppeteer’s managed-download defaults.

import puppeteer from 'puppeteer';

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

Set CHROME_EXECUTABLE to a path that exists in the runtime environment. The environment variable name in this example is your application’s own convention; Puppeteer’s documented override is PUPPETEER_EXECUTABLE_PATH.

Use a Chrome release channel

A channel tells Puppeteer to look for a regular Chrome installation in a known system location. The browser API’s computeSystemExecutablePath() likewise takes a release channel and checks known locations, throwing if it cannot find the expected executable. The references reviewed do not provide a complete cross-platform location table, so avoid hard-coding a guessed system path.

import puppeteer from 'puppeteer';

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

Use a channel only when the expected Chrome channel is installed in the machine or image where the code runs. A channel lookup is not a request to use Puppeteer’s cached download.

5. What changes with puppeteer-core

puppeteer-core is the library to use when your application supplies or manages the browser separately. Its configuration files and Puppeteer environment configuration are ignored. The PuppeteerNode API reference states that puppeteer-core requires options.executablePath or options.channel when launching.

import puppeteer from 'puppeteer-core';

const browser = await puppeteer.launch({
  executablePath: process.env.CHROME_EXECUTABLE,
  headless: true
});
try {
  const page = await browser.newPage();
  await page.goto('https://example.com');
  console.log(await page.title());
} finally {
  await browser.close();
}

Alternatively, provide a supported channel if a system Chrome installation is available. Do not expect puppeteer-core to download a browser or honor the full package’s cache configuration.

6. Find and fix “executable not found” problems

  1. Identify the package and version. Check whether the dependency is puppeteer or puppeteer-core. Confirm the version installed by the actual runtime, not only the version requested in package.json.
  2. Print the computed path. Call puppeteer.executablePath() in the failing process. Compare it with the path in the error and the filesystem in that same container or host.
  3. Inspect overrides. Check PUPPETEER_EXECUTABLE_PATH, PUPPETEER_CACHE_DIR, PUPPETEER_BROWSER, browser-specific download settings, configuration files, and any launch-time executablePath or channel.
  4. Check installation behavior. Determine whether browser downloads were skipped and whether the selected browser/build/platform was installed into the cache directory the runtime uses.
  5. Compare build and runtime environments. A browser installed during build can be missing after packaging, copying, or deploying to a fresh container if the cache was outside the artifact.
  6. For a channel, verify the system installation. The channel must be installed where Puppeteer runs; channel lookup fails when the expected executable is absent.
  7. Check access and runtime libraries. If the file exists but launch fails, verify that the runtime user can read and execute it and that the operating system image has the dependencies the browser needs.

7. Deployment and cache layout

Starting in Puppeteer v19.0.0, browser downloads are stored by default in ~/.cache/puppeteer to support a global cache. This can surprise deployments that package the Node application in one build location and move it to a fresh runtime: the browser cache may not travel with the package, or the runtime user may have a different home directory.

The configuration guide’s suggested remedy for this packaging pattern is to change cacheDirectory and reinstall Puppeteer so the browser is installed in that chosen location. Keep install-time and runtime cache settings aligned, and ensure the deployment artifact or image includes the browser files when needed. Check the documentation matching your installed version because cache behavior and package setup can change over time.

8. Compatibility, performance, reliability, and cost

Compatibility

Puppeteer says it is only guaranteed to work with its bundled browser. When you supply another Chrome or Chromium executable, you take on compatibility risk; a path resolving correctly does not establish that its browser version works with the Puppeteer package. Custom browser providers carry a similar caveat.

Performance and reliability

Executable-path computation is configuration and path resolution; the more consequential operational issue is whether the browser is already installed and accessible where the process runs. A managed browser in a stable, included cache avoids reliance on an undocumented system installation. A system channel can be convenient when the deployment controls Chrome installation, but channel lookup can fail if that assumption drifts. Explicit paths are predictable only when deployment keeps the path and binary aligned.

Cost

Puppeteer itself does not charge per executable-path lookup. Operational cost comes from obtaining, storing, updating, and running the browser and from the compute used by browser automation. Skipping downloads may reduce image size but leaves you responsible for supplying a compatible executable.

9. Or skip the browser setup

If the task is to capture a webpage rather than automate a browser, ScreenshotNeo provides a screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. See the API documentation for the request options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up free for 1,000 screenshots a month, with no card required.

10. Troubleshooting table

Symptom Likely cause What to do
executablePath() points somewhere unexpected A cache or executable override, config file, selected browser, or package version differs from your assumption Print the path and relevant environment values in the runtime; inspect its effective config and installed version
Path is returned, but file is missing Browser download was skipped, went to another cache, or was omitted from deployment Align install/runtime cache settings and ensure the browser is installed and included
Channel launch cannot find Chrome The requested channel is not installed in a recognized system location Install the channel in the runtime image or use a managed binary/explicit path
Works locally, fails after deployment Different home directory, cache location, package, or user in production Compare environment and filesystem in both environments; configure a deployment-local cache and install there
Path exists, but launch fails Permissions, OS dependencies, or browser/Puppeteer incompatibility Check executable access and system dependencies; use the bundled browser or a compatible external version
Environment variable appears ignored Using puppeteer-core, setting it only during runtime when install behavior matters, or overriding it in launch options For core, pass an explicit path or channel; set relevant install and runtime configuration consistently

11. FAQ

Does executablePath() install Chrome?

No. It returns the computed default location. Browser installation is a separate step.

Can I copy a path from another operating system?

Usually that is unsafe. The platform and browser archive determine the executable location and format.

Does setting channel use Puppeteer’s downloaded Chrome?

No. A channel selects a system installation through known locations.

Will any Chrome version work?

Puppeteer guarantees compatibility with its bundled browser. Treat an externally selected executable as a compatibility responsibility.

Where can I confirm the exact behavior?

Use the official configuration, browser API, launch options, and PuppeteerNode references for the installed version. The current references in this research dossier identify version 25.12.0.

Sources