Puppeteer Browser Download Options Explained
Choose Puppeteer’s bundled browser, install it manually, control its cache and downloads, or use a browser you manage yourself.
Short answer: install puppeteer and let it download its compatible browser for the simplest, best-supported setup. If your package manager blocks install scripts, run npx puppeteer browsers install yourself. If you manage the browser separately, use puppeteer-core and provide an executable path or channel; then you own version compatibility.
Puppeteer normally downloads Chrome for Testing and chrome-headless-shell. Its default browser cache is ~/.cache/puppeteer. You can change the cache, select a browser, skip downloads, or point launches to an executable with a configuration file or environment variables. See the official installation guide and configuration reference.
1. Choose a browser download approach
| Approach | Who installs and updates the browser? | Compatibility | Use it when |
|---|---|---|---|
puppeteer default install |
Puppeteer’s install process | Strongest documented assurance: the bundled browser is the one Puppeteer supports | You can download the browser during install and want the least setup |
| Manual Puppeteer browser install | You run Puppeteer’s browser installer | Still uses Puppeteer-managed browser builds | Install scripts are blocked or downloads need a deliberate step |
puppeteer-core plus your own browser |
You or your browser provider | You must validate browser and Puppeteer compatibility | You use a system, container, remote, or centrally managed browser |
Puppeteer’s installation guide currently gives approximate browser download sizes of 170 MB for macOS, 282 MB for Linux, and 280 MB for Windows. These are guide estimates, not fixed sizes for every version or installation. Include the download in build time and cache planning.
2. Install Puppeteer and its bundled browser
For a typical Node.js project, add Puppeteer as a dependency:
npm install puppeteer
Then use the bundled browser from a runnable JavaScript file such as screenshot.mjs:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.screenshot({ path: 'example.png', fullPage: true });
} finally {
await browser.close();
}
Run it with node screenshot.mjs. The regular puppeteer package downloads Chrome for Testing; chrome-headless-shell has also been included since Puppeteer v21.6.0. The default cache is under the home directory at .cache/puppeteer. Puppeteer documents globally cached browser files as the behavior since v19.0.0.
3. Install the browser manually when install scripts are blocked
Some package manager configurations or security policies prevent dependency lifecycle scripts from running. The library may install successfully while its browser download does not. The typical symptom is Could not find Chrome (ver. ...).
After installing the package, run Puppeteer’s installer explicitly:
npx puppeteer browsers install
Equivalent package manager invocations include:
yarn puppeteer browsers install
pnpm exec puppeteer browsers install
bunx puppeteer browsers install
These commands are appropriate when your project intentionally restricts install scripts. Another option is to allow Puppeteer’s install script under your package manager’s policy. Follow the policy for your package manager and repository rather than enabling all dependency scripts without review.
For a specific Chrome build, use the @puppeteer/browsers CLI. It accepts stable channel, milestone, or exact version selectors; verify the resulting executable path for your setup if you are installing outside Puppeteer’s normal cache.
npx @puppeteer/browsers install chrome@stable
npx @puppeteer/browsers install chrome@117
npx @puppeteer/browsers install chrome@116.0.5793.0
The CLI also supports platform and cache-directory settings, among other options. An expected SHA-256 hash can be supplied when using the browser management API; when provided, installation fails if the downloaded archive does not match. Do not assume checksum validation is enabled when no hash is supplied. See the browser management documentation.
4. Configure download behavior and cache location
Puppeteer configuration files are the clearest way to keep project settings together. For example, create .puppeteerrc.cjs in the project root:
/** @type {import('puppeteer').Configuration} */
module.exports = {
cacheDirectory: './.cache/puppeteer',
defaultBrowser: 'chrome',
// Set true only when a browser is installed or provided elsewhere.
skipDownload: false,
};
Use cacheDirectory to relocate the browser cache. For example, a project-local cache can be useful in a container image or CI workflow, provided the directory is persisted or populated during image construction. If you change download-related configuration after installing Puppeteer, run the browser install command again so the browser is available at the configured location.
Environment variables can override corresponding settings:
| Setting | Configuration key | Environment variable | Purpose |
|---|---|---|---|
| Cache path | cacheDirectory |
PUPPETEER_CACHE_DIR |
Choose where downloaded browsers are stored |
| Skip all downloads | skipDownload |
PUPPETEER_SKIP_DOWNLOAD |
Prevent browser downloads during installation |
| Skip a browser download | Browser-specific settings | PUPPETEER_CHROME_SKIP_DOWNLOAD, PUPPETEER_FIREFOX_SKIP_DOWNLOAD |
Skip a particular browser’s download |
| Default browser | defaultBrowser |
PUPPETEER_BROWSER |
Select Chrome or Firefox as the default |
| Executable path | executablePath |
PUPPETEER_EXECUTABLE_PATH |
Set the path used when launching |
Chrome- and Firefox-specific configuration also includes browser versions and download base URLs. Treat custom download locations and providers as operational choices you must maintain. Puppeteer labels custom browser providers unsupported; compatibility, testing, and upkeep are your responsibility.
To set a cache location for one shell session:
# macOS or Linux
PUPPETEER_CACHE_DIR="$PWD/.cache/puppeteer" npx puppeteer browsers install
# PowerShell
$env:PUPPETEER_CACHE_DIR = "$PWD\.cache\puppeteer"
npx puppeteer browsers install
Configuration files and Puppeteer environment variables are ignored by puppeteer-core. Configure the browser path explicitly when using that package.
5. Skip the download and use a browser you manage
Choose puppeteer-core when another system supplies the browser, such as a remote browser service or a system installation you manage. It does not download Chrome. Install it with:
npm install puppeteer-core
Provide an explicit executable path or a Chrome channel when launching. An executable path identifies a particular browser binary; a channel asks Puppeteer to find a standard Chrome installation. This complete example uses an explicit path from an environment variable:
import puppeteer from 'puppeteer-core';
const executablePath = process.env.CHROME_PATH;
if (!executablePath) {
throw new Error('Set CHROME_PATH to the browser executable');
}
const browser = await puppeteer.launch({
executablePath,
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();
}
Alternatively, where a standard Chrome channel is installed, launch with channel: 'chrome'. Do not set both a channel and an executable path unless you have a specific reason and have checked the launch option behavior for your Puppeteer version.
const browser = await puppeteer.launch({ channel: 'chrome', headless: true });
Puppeteer says it works best with the browser it downloads and only guarantees compatibility with the bundled browser. With a separately managed browser, pin or control browser updates where practical and validate launch, navigation, and the automation features your application uses. A successful launch alone does not guarantee every protocol feature behaves as expected.
6. Select Chrome or Firefox with version awareness
Puppeteer supports Chrome and Firefox, but the supported browser build is tied to the Puppeteer release. Check the supported browsers table for the version you actually installed instead of copying a version number from an older post. For context, the documentation labeled 25.12.0 paired that release with Chrome for Testing 154.0.8037.57 and Firefox 156.0.1; these are dated examples, not permanent recommendations.
When selecting Firefox, set defaultBrowser: 'firefox' and install the relevant browser build through Puppeteer’s documented installation flow. Review the browser-specific configuration for version and download settings. If you use a custom provider, mirror, or separately managed build, take responsibility for verifying compatibility.
7. Make browser downloads reliable in CI and containers
- Pin dependencies: commit the lockfile so package installation does not silently change the Puppeteer release and its paired browser expectation.
- Make installation explicit: when install scripts are disabled, include
npx puppeteer browsers installas a build step after dependencies are installed. - Cache the right directory: persist the configured cache directory between builds, or install the browser in the image build stage. A cache from another platform or incompatible Puppeteer release may not be usable.
- Check Linux runtime dependencies: a downloaded browser can still fail to start if required operating system libraries are absent. Use the Puppeteer troubleshooting and system requirements documentation for the target distribution.
- Control upgrades: changing the Puppeteer package can change the expected browser build. Rebuild or refresh the browser cache alongside dependency updates.
- Account for disk and network limits: browser archives are large compared with typical JavaScript packages. Avoid downloading them independently for every parallel job where a safe shared cache or prebuilt image is available.
Do not treat a system Chrome version as interchangeable with Puppeteer’s downloaded build merely because both identify as Chrome. Their protocol behavior can differ, and Puppeteer’s compatibility guarantee applies to its bundled browser.
8. cURL, Python, and Node.js alternatives for a one-off screenshot
If the goal is only to obtain a website screenshot rather than run browser automation code, you may not need to install or maintain a local browser. ScreenshotNeo is a website screenshot API and MCP server for developers. Its one-call API accepts a URL and returns an image or PDF; the examples below request a WebP screenshot. 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
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 Bun.write('shot.webp', res);
The Node example uses Bun’s file writer. In Node.js, save the response with:
import { writeFile } from 'node:fs/promises';
const bytes = new Uint8Array(await res.arrayBuffer());
await writeFile('shot.webp', bytes);
Keep API keys on the server or in environment variables; do not expose a private key in browser-side JavaScript or a public repository. The API can also return PNG, JPEG, or PDF and offers capture controls including full-page capture, element selection, viewport and device presets, wait conditions, cookies, headers, custom CSS and JavaScript, caching, async jobs, and bulk capture. Consult the docs for parameter names and response behavior.
9. Or skip the browser setup
Use ScreenshotNeo when your task is to capture pages rather than control a local browser. It removes cookie banners, popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. An 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.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Create a free account for 1,000 screenshots a month, with no card required.
10. Troubleshooting browser downloads
| Symptom | Likely cause | Fix |
|---|---|---|
Could not find Chrome (ver. ...) |
The package install script did not run, the browser was never installed, or the configured cache differs from the install cache. | Run npx puppeteer browsers install. Check PUPPETEER_CACHE_DIR and the config file used during installation and runtime. |
puppeteer-core launches without a browser or reports a missing executable |
puppeteer-core does not download a browser and needs a path or channel. |
Install/manage a compatible browser and pass executablePath or channel to launch(). |
| Browser download succeeds, but launch fails on Linux | Required system libraries or runtime dependencies may be missing. | Check Puppeteer’s system requirements and troubleshooting guide for your distribution; install the missing operating system dependencies. |
| Browser is installed in one location but Puppeteer cannot find it | The cache directory changed between install time and runtime, or the process runs as a different user with a different home directory. | Use the same cache setting in both stages, or supply the executable path explicitly. |
| Download repeatedly fails or stalls | Network restrictions, proxy rules, or insufficient disk space can interrupt a large browser archive. | Check outbound access to the configured download host, proxy configuration, disk space, and whether the build environment permits the download. Retry the explicit installer after resolving the restriction. |
| Custom Chrome starts but automation behaves inconsistently | The browser version may not match the Puppeteer release. | Use the paired browser from the supported browser table, or pin and validate the separately managed browser against your workload. |
| Firefox archive cannot unpack | The host may lack the archive utilities required by the platform. | Install the required unpacking utilities listed in the browser management documentation for that operating system. |
11. Performance, reliability, and cost considerations
- Build time: the browser download adds network transfer and extraction time. Install once in a build image or preserve the cache when your environment supports it.
- Storage: browser binaries consume substantial disk space. Remove obsolete browser builds only when they are no longer needed by active jobs.
- Repeatability: the bundled browser tracks the Puppeteer release and is the predictable default. A system browser may update independently unless your deployment pins it.
- Failure isolation: make browser installation a distinct build step so download, extraction, and runtime dependency failures are visible before application execution.
- Managed capture cost: a local Puppeteer setup has no per-screenshot API charge from Puppeteer itself, but you operate the browser infrastructure and absorb its download, storage, and compute costs. ScreenshotNeo’s free plan offers 1,000 shots/month; paid plans are $5 for 3,000, $15 for 15,000, $39 for 60,000, $99 for 250,000, and $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan.
12. Frequently asked questions
Can I install Puppeteer without downloading Chrome?
Yes. Configure skipDownload or PUPPETEER_SKIP_DOWNLOAD, or install puppeteer-core. You still need to provide a browser when launching.
Where does Puppeteer download Chrome?
The documented default browser cache is ~/.cache/puppeteer. Change it with cacheDirectory or PUPPETEER_CACHE_DIR.
Can I use my installed Chrome?
Yes. Use puppeteer-core or set an executable path/channel for launch. Since it is not the bundled browser, verify compatibility with your Puppeteer version.
Should I choose the system Chrome channel or a path?
Use a channel when you want Puppeteer to locate a standard Chrome installation. Use a path when deployment needs a specific executable location or version.
Does puppeteer-core read my Puppeteer config file?
No. Puppeteer configuration files and Puppeteer environment variables are ignored by puppeteer-core; pass browser launch details directly.
How do I know which browser version matches my Puppeteer release?
Check the official supported browsers table for the version in your lockfile. The mapping changes with releases.


