Puppeteer Browser Installation Options Explained
Choose between Puppeteer’s bundled browser, a manual browser install, and puppeteer-core. Learn how to configure each route and fix missing-browser errors.
Short answer: Install puppeteer when you want Puppeteer to download a compatible browser for you. Install puppeteer-core when you manage the browser yourself or connect to one remotely. If package installation skips browser downloads, install the browser explicitly with Puppeteer’s browser command. You can also point Puppeteer at a system Chrome, but compatibility with an arbitrary external version is not guaranteed.
The right choice depends on who owns the browser version, whether your package manager runs install scripts, and whether Chrome runs locally or remotely. This guide uses the Puppeteer 25.12.0 documentation as a versioned reference; check the current documentation before pinning a browser version or runtime requirement.
Choose an installation route
| Route | Choose it when | What you manage |
|---|---|---|
puppeteer |
You want a straightforward local or CI setup with Puppeteer’s paired browser. | Package installation must be allowed to download browser binaries; keep package versions and install steps consistent. |
puppeteer plus manual browser install |
Install scripts are blocked, or you want browser installation to be a separate, explicit build step. | Run the browser install command and make the browser cache available to the runtime. |
puppeteer-core plus a managed browser |
You own browser provisioning, use a remote browser, or need explicit control over executable versions and paths. | Supply a local executable path or channel, or connect to a remote browser. Validate compatibility and upgrades. |
puppeteer plus system Chrome |
A workstation or CI image already has Chrome installed and you want Puppeteer to use it. | Choose a channel or executable path and check browser compatibility yourself. |
Puppeteer’s installation guide says the puppeteer package downloads Chrome for Testing and, since v21.6.0, chrome-headless-shell. The documented default browser cache is $HOME/.cache/puppeteer since v19.0.0. The guide gives approximate download sizes of 170 MB on macOS, 282 MB on Linux, and 280 MB on Windows; these are download-size estimates, not install-time benchmarks. See the [official installation guide](https://pptr.dev/guides/installation).
Prerequisites and compatibility
The current system-requirements page lists Node.js 22.12 or newer for the documented release. It lists Chrome for Testing support on Windows x64; macOS x64 and arm64; Debian/Ubuntu Linux x64 and arm64; and openSUSE/Fedora Linux x64 and arm64. Chrome archive extraction requires tar.exe or PowerShell on Windows, and unzip on macOS/Linux, unless the optional yauzl dependency is installed. Linux browser packages may also be required. Requirements can change by release; see [Puppeteer system requirements](https://pptr.dev/guides/system-requirements).
Puppeteer’s supported-browser table maps Puppeteer 25.12.0 to Chrome for Testing 154.0.8037.57. That mapping is version-specific and will change; consult the [supported browsers table](https://pptr.dev/chromium-support/) when you pin versions. Puppeteer says it works best with its bundled browser and does not guarantee compatibility with other versions.
Option 1: Install Puppeteer with its browser
For the convenience route, install the package with your package manager:
# npm
npm install puppeteer
# Yarn
yarn add puppeteer
# pnpm
pnpm add puppeteer
# Bun
bun add puppeteer
Here is a complete runnable Node.js example that opens a page and saves a screenshot. Save it as capture.mjs, install Puppeteer, then run node capture.mjs.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.setViewport({ width: 1365, height: 900 });
await page.goto('https://example.com', {
waitUntil: 'networkidle2',
timeout: 30_000,
});
await page.screenshot({ path: 'example.png', fullPage: true });
} finally {
await browser.close();
}
This route is simplest when dependency installation is allowed to run Puppeteer’s postinstall script. In locked-down or reproducible build environments, make browser provisioning explicit instead of assuming that a package install downloaded it.
Option 2: Install the browser manually
Some package manager configurations block dependency install scripts. In that case, the package can install without its browser, and launching Puppeteer may fail with Could not find Chrome (ver. ...). Run the browser installation command as a deliberate setup step:
# npm
npx puppeteer browsers install
# Yarn
yarn dlx puppeteer browsers install
# pnpm
pnpm dlx puppeteer browsers install
# Bun
bun x puppeteer browsers install
Alternatively, allow Puppeteer’s postinstall script according to your package manager’s policy. For example, the current Puppeteer installation guide shows an allowScripts entry for npm configurations that support it:
{
"allowScripts": {
"puppeteer": true
}
}
In CI, run the browser install step in the same build or image that supplies the runtime, and preserve the configured cache between build and execution if the environment requires it. Do not assume the cache is shared across separate containers or users.
Option 3: Manage a browser build and cache yourself
The @puppeteer/browsers CLI can install Chrome for Testing by channel, version, or milestone. Install stable, an exact build, or a milestone as shown here:
npx @puppeteer/browsers install chrome@stable
npx @puppeteer/browsers install chrome@154.0.8037.57
npx @puppeteer/browsers install chrome@154
Use an exact build when repeatability matters, and update it deliberately alongside Puppeteer. A channel such as stable follows the available stable build, so it is less suitable when every deployment must use an unchanged browser binary. See the [browser management CLI documentation](https://pptr.dev/browsers-api).
For programmatic installs, Puppeteer’s browser API exposes choices including browser, build ID, platform, and cache directory. Its install options also support an expected SHA-256 hash; when provided, installation fails if the downloaded file does not match. The API documents installDeps for Chrome on Debian/Ubuntu only, and it requires system privileges. See [InstallOptions](https://pptr.dev/browsers-api/browsers.installoptions).
Configuration for the puppeteer package can be set through a Puppeteer configuration file or environment variables. Relevant settings include:
| Setting | Purpose | Environment variable |
|---|---|---|
defaultBrowser |
Select the browser family used for default downloads and behavior. | PUPPETEER_BROWSER |
executablePath |
Use a specific browser executable at launch. | PUPPETEER_EXECUTABLE_PATH |
cacheDirectory |
Choose where downloaded browser binaries are cached. | PUPPETEER_CACHE_DIR |
skipDownload |
Skip browser download during package installation. | PUPPETEER_SKIP_DOWNLOAD |
| Chrome-specific download setting | Skip Chrome download specifically. | PUPPETEER_CHROME_SKIP_DOWNLOAD |
Use skipDownload only if another step provisions the browser. Puppeteer configuration and its environment variables are ignored by puppeteer-core; with that package, provide launch or connection details directly. See the [configuration guide](https://pptr.dev/guides/configuration).
Option 4: Use system Chrome or connect remotely
If Chrome is already installed in a standard location, use a release channel; otherwise set an explicit executable path. With puppeteer, the package still includes Puppeteer’s defaults, but an explicit launch option selects the external browser.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
headless: true,
channel: 'chrome',
});
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
console.log(await page.title());
} finally {
await browser.close();
}
To select a particular executable, replace channel with executablePath:
const browser = await puppeteer.launch({
headless: true,
executablePath: '/usr/bin/google-chrome',
});
Paths differ by operating system, package, and machine image. Confirm the executable exists and is runnable under the same user as your Node process. For a remote browser, use puppeteer-core and connect using the remote browser’s supported endpoint rather than launching a local executable; see the [Puppeteer API documentation](https://pptr.dev/api/puppeteer.puppeteer.connect).
Option 5: Use puppeteer-core
puppeteer-core does not download Chrome when installed. It is intended for remote browser connections and separately managed browsers. A local executable example:
npm install puppeteer-core
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.launch({
executablePath: process.env.CHROME_PATH ?? '/usr/bin/google-chrome',
headless: true,
});
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'example.png' });
} finally {
await browser.close();
}
Set CHROME_PATH to the real browser executable on the machine. If using a remote browser, configure a connection endpoint instead of executablePath. You own browser provisioning, compatibility checks, upgrades, and the operational consequences of mismatched versions. Puppeteer’s installation guide explains the distinction between [puppeteer and puppeteer-core](https://pptr.dev/guides/installation).
How to decide
- Need the paired browser with minimal setup? Install
puppeteerand allow its browser download. - Install scripts are blocked? Install
puppeteer, then runpuppeteer browsers installas an explicit setup step. - Need fixed browser builds or custom cache placement? Use browser management tools, record the chosen build, and set a deliberate cache directory.
- Already have Chrome? Use
channelorexecutablePath, then validate the version against the Puppeteer release you deploy. - Using a remote browser or browser fleet? Use
puppeteer-coreand configure its connection or executable directly.
For a custom browser provider, Puppeteer places compatibility, testing, and maintenance responsibility on the user. A custom executable may launch successfully but still behave differently or lack expected integration with Puppeteer. The [browser installation API documentation](https://pptr.dev/browsers-api/browsers.installoptions) describes these compatibility responsibilities.
cURL, Python, and Node.js examples for a one-off screenshot
If your goal is one screenshot rather than maintaining a browser installation, the same task can be done through ScreenshotNeo’s screenshot API. These examples use the documented API endpoint and target URL. See the [ScreenshotNeo documentation](https://screenshotneo.com/docs/).
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
r.raise_for_status()
with open("shot.webp", "wb") as output:
output.write(r.content)
Node.js
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 import('node:fs/promises').then(({ writeFile }) =>
writeFile('shot.webp', Buffer.from(await res.arrayBuffer()))
);
Or skip the browser setup
Make one API request to get a screenshot, without installing or maintaining a local browser. ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step 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. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. [ScreenshotNeo](https://screenshotneo.com) also supports PDF output and many capture controls; see the [API documentation](https://screenshotneo.com/docs/).
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
Create a free account for 1,000 screenshots a month, with no card required.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Could not find Chrome (ver. ...) |
The package installed but its postinstall browser download was skipped or the browser cache is missing. | Run npx puppeteer browsers install (or the equivalent for your package manager), or permit Puppeteer’s postinstall script. Check that install and runtime use the same configured cache directory. |
| Browser executable does not exist or cannot launch | A channel is unavailable, the configured path is wrong, or the runtime user cannot execute the file. | Check the path and file permissions in the runtime environment. Use a channel only when Chrome is installed in a standard location. |
| Works locally but fails in CI or a container | The build image may have skipped install scripts, not preserved the browser cache, or lack platform browser dependencies. | Add an explicit browser installation step, keep cache configuration consistent, and follow the operating-system requirements for your Puppeteer release. |
| External Chrome launches but features fail or behavior differs | The selected Chrome build may not match the Puppeteer release. | Prefer Puppeteer’s bundled browser, or choose a supported version and validate your own browser/Puppeteer pairing. |
| Download fails while unpacking | The operating system may lack the required archive utility, or the cache directory may not be writable. | Install the documented extraction utility for that platform and make the cache directory writable by the installing user. |
puppeteer-core starts without a browser |
puppeteer-core has no default downloaded browser and ignores Puppeteer configuration defaults. |
Pass an explicit executable path or connect to a remote browser using its supported endpoint. |
| Browser download consumes unexpected disk space | Puppeteer installs Chrome for Testing and, for releases since v21.6.0, a separate chrome-headless-shell. |
Account for both binaries in build cache and image planning. Change download behavior only when another browser provisioning step is in place. |
Performance, reliability, and cost considerations
- Install and storage: Puppeteer’s documented browser downloads are substantial, and the guide lists approximate per-platform sizes. Cache browser binaries in repeatable build environments where appropriate, but ensure the runtime can access the same cache.
- Repeatability: Pin the Puppeteer package and, when managing browsers separately, select a specific browser build rather than relying on a moving channel. Update and validate the pair deliberately.
- Reliability: Treat browser installation as part of environment provisioning. A package lockfile alone does not ensure a browser binary exists if install scripts are blocked or build caches are discarded.
- Maintenance: Bundled installation transfers more browser setup to Puppeteer. With
puppeteer-coreor a custom browser provider, your team owns path configuration, compatibility checks, testing, and updates. - Cost: Browser binaries consume download bandwidth, build time, and disk space. The official download-size figures are not runtime or performance benchmarks. A screenshot API instead has its own usage plan and request limits; check the provider’s current pricing before adopting it.
FAQ
How do I install Puppeteer?
Run npm install puppeteer, or use Yarn, pnpm, or Bun. If install scripts are blocked, run npx puppeteer browsers install after installation.
How do I install Chrome for Puppeteer?
For Puppeteer’s paired browser, install the puppeteer package or run its browser install command explicitly. For a separately managed Chrome build, use npx @puppeteer/browsers install chrome@stable, a version, or a milestone.
Can I use my own Chrome installation?
Yes. Set channel for a standard Chrome installation or pass an executablePath. Puppeteer recommends its bundled version and does not guarantee arbitrary external versions.
Does puppeteer-core install Chrome?
No. It is intended for a browser you manage or a remote browser, and needs a browser path or connection configured by your application.
Can I make browser installation smaller?
You can skip downloads or manage them separately, but then another step must supply the browser your program launches. Plan storage around the selected browser binaries and cache.


