ScreenshotNeo

BlogHow-to

How Puppeteer Finds a Downloaded Browser Executable

Puppeteer uses an explicit executable path when configured; otherwise, it builds a path from the browser, version, and cache directory. Here’s how to trace and fix it.

By the ScreenshotNeo team4 October 20267 min read

Puppeteer launches the executable at executablePath if you configured one. Otherwise, it calculates the expected executable path from the selected browser, its expected build, and Puppeteer’s cache directory, then checks that the file exists. If the browser was never downloaded, the cache differs between installation and runtime, or the selected browser type does not match, launch fails.

For the default puppeteer package, a browser download is normally part of installation. The default cache is ~/.cache/puppeteer starting with Puppeteer v19.0.0. puppeteer-core does not download a browser, so you must manage one yourself and pass its path or a standard installation channel. See the official configuration guide, installation guide, configuration API, and launcher source.

How Puppeteer resolves the executable

  1. Explicit path: executablePath in launch options or the PUPPETEER_EXECUTABLE_PATH environment variable takes precedence. With validation enabled, Puppeteer throws if that path does not exist.
  2. Calculated path: Without an explicit path, Puppeteer determines the browser type and expected build, gets its configured cache directory, and computes the corresponding executable location.
  3. Existence check: Puppeteer checks that the calculated executable is present. If not, it reports that browser installation may not have run or the cache may be misconfigured.

The browser type and launch mode matter. Regular Chrome uses the Chrome build; headless: 'shell' uses Chrome Headless Shell; Firefox uses Firefox. A browser of a different type or build in the cache will not satisfy the computed path.

Where the browser is downloaded

The default cache directory is path.join(os.homedir(), '.cache', 'puppeteer'), commonly shown as $HOME/.cache/puppeteer. Set PUPPETEER_CACHE_DIR to override it, or configure cacheDirectory in Puppeteer’s configuration. Environment variables take precedence over configuration file values when applicable.

Because the cache is outside the project by default, copying a project to another machine or a fresh container does not necessarily copy its browser. The runtime must see a compatible browser in the cache it is configured to use. If you change settings that affect browser downloads, rerun the install step so the download follows the new configuration.

Install the browser Puppeteer expects

  1. Use puppeteer if you want its installation process to download a compatible browser automatically.
  2. If your package manager blocks install scripts, run npx puppeteer browsers install after installing the package. You can also allow Puppeteer’s install script under your package manager’s policy.
  3. Keep the cache configuration consistent between installation and runtime. If you set PUPPETEER_CACHE_DIR in one environment but not the other, Puppeteer can download to one directory and search another.
  4. Use puppeteer-core when you intentionally manage the browser yourself, for example when connecting to a remote browser. Provide executablePath or use channel for a browser installed in a standard location.
npm install puppeteer
npx puppeteer browsers install

The explicit install command is useful even after package installation: it makes the browser installation step visible in a build or deployment workflow, including environments where install scripts are disabled.

Configure a browser Puppeteer manages

For a Puppeteer-managed download, normally omit executablePath. Puppeteer will compute the path for the selected browser and build from its configured cache. This runnable example launches the installed default browser and prints its executable path:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  console.log('Executable:', browser.process()?.spawnfile);
  await browser.close();
})().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

Run it with node launch.js. If you use ES modules, replace the first line with import puppeteer from 'puppeteer';. The reported path helps confirm which binary was launched; it does not install a missing browser.

Configure an externally managed browser

If you installed Chrome yourself or use puppeteer-core, provide the real executable path. The path must exist in the same runtime environment where Node runs, including inside a container or server.

const puppeteer = require('puppeteer-core');

(async () => {
  const browser = await puppeteer.launch({
    executablePath: '/absolute/path/to/chrome',
    headless: true
  });
  console.log('Executable:', browser.process()?.spawnfile);
  await browser.close();
})().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

Replace the placeholder with the installed browser’s actual path. A standard-location installation can instead be selected with Puppeteer’s channel option, as described in the official installation guide. Do not assume a path from your laptop also exists on a CI runner or container.

Choose between managed and external browsers

Setup Who installs and updates it? How Puppeteer locates it What to keep aligned
puppeteer managed browser Puppeteer’s install process Computed path in the configured cache Package version, browser build, cache setting, and launch browser type
External browser with puppeteer-core Your deployment or browser provider Explicit executablePath or standard-location channel Actual binary path and availability in the runtime environment

The managed route reduces path maintenance when the install step runs reliably. The external route is useful when your environment owns browser installation, but you must make sure its binary exists and is compatible where the script runs.

Diagnose “Could not find Chrome” and path errors

  1. Check the package. If the code imports puppeteer-core, no browser download is performed for you. Either install and manage a browser yourself, or use puppeteer.
  2. Check whether installation scripts ran. Package-manager policies may block lifecycle scripts. Run npx puppeteer browsers install in the build environment.
  3. Check the cache used by both steps. Inspect PUPPETEER_CACHE_DIR and the cacheDirectory configuration. Make sure download and launch happen with the same effective setting.
  4. Check explicit overrides. Look for executablePath in launch options and PUPPETEER_EXECUTABLE_PATH in the environment. An explicit path takes precedence over cache lookup; remove a stale override or point it to an existing file.
  5. Check browser type and mode. A Chrome Headless Shell install does not fulfill a request for regular Chrome, and the reverse is also true. Match the installed browser to the launch configuration.
  6. Check the runtime filesystem. Confirm that the executable exists in the container, server, or CI job that launches Puppeteer. A local path is not automatically available remotely.
Symptom Likely cause Fix
“Could not find Chrome” or browser missing Browser download did not run, or Puppeteer is looking in another cache Run npx puppeteer browsers install; align cache settings
Configured executable path does not exist Stale or machine-specific executablePath or environment override Check the path in the runtime environment, then correct or remove the override
Works locally, fails in CI or a container Browser cache or external binary was not included or installed in that environment Install the browser during the image/build process, or configure a browser path available there
Headless launch cannot find the expected binary Launch mode resolves to a different browser type, such as Chrome Headless Shell Install the matching browser build or select the intended mode
Changing config has no effect Environment variable overrides the config file, or the browser was not reinstalled after changing download settings Inspect environment overrides and rerun the browser install command

Or skip the browser setup

If your goal is a website screenshot rather than browser automation, ScreenshotNeo returns an image or PDF from one GET request. It avoids installing and locating a browser in your application. See the ScreenshotNeo API documentation.

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

Cookie banners are accepted or removed before the shot, along with known newsletter popups and chat widgets. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers say the page verdict and billing status. An MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Every plan includes every feature.

Sign up free for 1,000 screenshots a month, no card required.

Performance, reliability, and cost considerations

  • Installation and deployment: Browser downloads add a build-time dependency. Install once in the image or build environment and ensure that the runtime uses the same cache or supplied executable.
  • Reliability: Treat browser type, expected build, cache directory, and runtime filesystem as one configuration. A mismatch can produce a missing-executable failure before page capture begins.
  • Updates: Reinstall according to Puppeteer’s configuration after changing browser download settings. Avoid assuming a manually managed browser remains at the path your deployment expects.
  • Cost: This dossier provides no benchmark or monetary estimate for Puppeteer browser installation or runtime. The relevant operational costs depend on your deployment and browser management choices. If you only need screenshots, ScreenshotNeo offers 1,000 monthly shots free and paid plans from $5 for 3,000.

FAQ

Does Puppeteer always download Chrome?

puppeteer normally downloads a compatible browser during installation. puppeteer-core does not. Install scripts blocked by package-manager policy can also prevent the download.

Can I change where Puppeteer stores browsers?

Yes. Set PUPPETEER_CACHE_DIR or configure cacheDirectory. Keep the effective setting consistent when installing and launching.

Should I set executablePath for the downloaded browser?

Usually not. Let Puppeteer compute the path for its managed browser. Set it when you manage the browser outside Puppeteer’s cache.

Why does a path that exists still fail?

Check that the path points to the intended browser executable and that it exists in the process’s runtime environment. Also check for a browser-type or launch-mode mismatch.

What does channel do?

It selects a browser installed in a standard location. Use it when managing a standard browser installation yourself; otherwise use Puppeteer’s managed download or an explicit executable path.