How to Skip Puppeteer’s Browser Download During Installation
Stop Puppeteer from downloading Chrome during install with an environment variable or project config, then connect to a browser you manage.
Set PUPPETEER_SKIP_DOWNLOAD=true before installing puppeteer.
PUPPETEER_SKIP_DOWNLOAD=true npm install puppeteer
This prevents Puppeteer’s installation hook from downloading a browser. It does not install or provide a browser for runtime. If your program launches a local browser, install one separately and pass its executable path or channel. If you connect to a remote browser or manage browsers yourself, use puppeteer-core. See the official Puppeteer installation guide and configuration reference.
Choose the right way to skip the download
| Method | Best for | Scope |
|---|---|---|
PUPPETEER_SKIP_DOWNLOAD=true |
One shell command, CI job, or deployment environment | That install process and its environment |
skipDownload: true |
A setting that should live with the project | Project configuration |
chrome.skipDownload: true |
Skipping Chrome while keeping other browser settings independent | Chrome-specific configuration |
puppeteer-core |
Remote or self-managed browsers | No Puppeteer browser download; configuration files and Puppeteer environment variables are ignored |
Option 1: use the environment variable
npm
PUPPETEER_SKIP_DOWNLOAD=true npm install puppeteer
pnpm
PUPPETEER_SKIP_DOWNLOAD=true pnpm add puppeteer
Yarn
PUPPETEER_SKIP_DOWNLOAD=true yarn add puppeteer
Set the variable in the same environment where the package manager runs, before the install script starts. On Windows PowerShell:
$env:PUPPETEER_SKIP_DOWNLOAD = "true"
npm install puppeteer
On Windows Command Prompt:
set PUPPETEER_SKIP_DOWNLOAD=true && npm install puppeteer
For a CI job, define the variable in that job’s environment rather than relying on a developer’s local shell profile.
Option 2: save the setting in project configuration
Puppeteer supports project configuration files such as .puppeteerrc.json, .puppeteerrc.js, puppeteer.config.js, and a puppeteer property in package.json. A JSON configuration is portable:
{
"skipDownload": true
}
Example .puppeteerrc.js:
/** @type {import('puppeteer').Configuration} */
module.exports = {
skipDownload: true,
};
Example in package.json:
{
"name": "capture-worker",
"puppeteer": {
"skipDownload": true
}
}
Environment variables take precedence when applicable. After changing download options, rerun the relevant installation step. Puppeteer documents npx puppeteer browsers install for installing browsers according to the current configuration.
Skip only Chrome
The global setting applies to browser downloads generally. If you need browser-specific control, use Chrome’s setting:
/** @type {import('puppeteer').Configuration} */
module.exports = {
chrome: {
skipDownload: true,
},
};
The corresponding environment override is:
PUPPETEER_CHROME_SKIP_DOWNLOAD=true npm install puppeteer
Use the global variable when every Puppeteer-managed browser download should be suppressed; use the browser-specific setting when your project needs different behavior by browser.
What changes at runtime
Skipping installation only removes the automatic download. A normal puppeteer launch still needs a browser executable available on the machine.
Launch a system browser by executable path
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
executablePath: process.env.CHROME_PATH,
headless: true,
});
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
console.log(await page.title());
await browser.close();
Set CHROME_PATH to the browser installed by your operating system, container image, or deployment platform. A channel can be used instead when Puppeteer should locate a standard installed browser channel:
const browser = await puppeteer.launch({
channel: 'chrome',
headless: true,
});
Confirm that the browser version is supported by your Puppeteer release. Puppeteer publishes a version mapping in its supported browsers page; do not assume any arbitrary system Chrome is interchangeable.
Use a remote browser with puppeteer-core
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.connect({
browserWSEndpoint: process.env.BROWSER_WS_ENDPOINT,
});
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
await browser.close();
puppeteer-core is intended for users connecting to a remote browser or managing browsers themselves. Its configuration files and Puppeteer environment variables are ignored, and installing it does not download Chrome.
Complete installation examples
Local browser supplied by your image or host
mkdir capture-worker
cd capture-worker
npm init -y
PUPPETEER_SKIP_DOWNLOAD=true npm install puppeteer
import puppeteer from 'puppeteer';
const executablePath = process.env.CHROME_PATH;
if (!executablePath) {
throw new Error('Set CHROME_PATH to an installed Chrome or Chromium executable');
}
const browser = await puppeteer.launch({ executablePath, headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'example.png', fullPage: true });
} finally {
await browser.close();
}
Remote browser service
npm init -y
npm install puppeteer-core
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.connect({
browserWSEndpoint: process.env.BROWSER_WS_ENDPOINT,
});
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.screenshot({ path: 'example.png' });
await browser.close();
Package-manager scripts and locked-down CI
Some package managers or CI policies block dependency install scripts. That can also prevent Puppeteer’s automatic browser download, even when you did not set a skip variable. If the application needs a local browser, either allow Puppeteer’s install script or install the browser explicitly with Puppeteer’s browser installer, following the official installation instructions.
Keep the install policy and runtime setup together: a reproducible build should document where the browser comes from, which executable path is used, and how the version is checked.
Docker and deployment checklist
- Set
PUPPETEER_SKIP_DOWNLOAD=trueduring dependency installation. - Install a supported Chrome or Chromium package in the image, or provide a remote browser endpoint.
- Set
CHROME_PATH(or use a supportedchannel) when launching locally. - Run the browser with the sandbox settings required by your container runtime; follow your platform’s security policy.
- Cache the package manager directory, not an accidentally downloaded browser, when the goal is to reduce build traffic.
- Verify the installed Puppeteer release against its browser support matrix.
Performance, reliability, and cost considerations
Build performance
Skipping the download reduces install time and network use. Puppeteer’s documentation lists approximate automatic-download sizes of about 170 MB on macOS, 282 MB on Linux, and 280 MB on Windows. Treat those as platform-specific estimates, not guaranteed transfer sizes.
Runtime reliability
The trade-off is operational responsibility. A missing executable, incompatible browser revision, missing shared library, or blocked sandbox can turn a successful install into a runtime failure. Pin the browser source used by your image or host and check the Puppeteer support matrix for the release you deploy.
Cost
The skipped download does not remove browser compute, storage, or network costs elsewhere. A self-managed browser still consumes resources; a remote browser usually charges according to its provider’s plan. Measure cold-start time and concurrency in the environment where the worker runs.
Common errors and fixes
| Error or symptom | Cause | Fix |
|---|---|---|
Could not find Chrome or a missing executable error |
The download was skipped and no browser was supplied | Install a supported browser and set executablePath or channel, or connect with puppeteer-core. |
| The browser downloads anyway | The variable was set after installation, misspelled, or applied to a different package-manager process | Set PUPPETEER_SKIP_DOWNLOAD=true before install and rerun it. Check the effective CI environment. |
| Configuration has no effect | The file name, location, or property is wrong | Use a supported project file and the exact skipDownload property. Remember that puppeteer-core ignores these files. |
| Only Chrome should be skipped, but another browser is affected | A global setting was used | Use the browser-specific setting such as chrome.skipDownload or PUPPETEER_CHROME_SKIP_DOWNLOAD. |
| Install succeeds but launch fails in CI | Install scripts were blocked or the image lacks browser dependencies | Allow the install script or install the browser explicitly; add required OS libraries and verify the executable path. |
| Protocol or launch errors after a browser upgrade | The browser and Puppeteer versions are outside the supported mapping | Check the release’s supported-browser table and align the versions. |
| Environment setting appears ignored | A stale installation or cached dependency was reused | Rerun the installation step with the setting present and invalidate the relevant package-manager cache. |
How to verify the setting
- Remove the existing installation or use a clean workspace.
- Run the package-manager command with
PUPPETEER_SKIP_DOWNLOAD=true. - Inspect the install log to confirm no browser archive was fetched.
- Run a launch smoke test with an explicit
executablePath,channel, or remote endpoint. - Record the Puppeteer and browser versions in build logs.
Or skip the browser setup
If your goal is simply to produce website screenshots, ScreenshotNeo provides a one-request screenshot API and MCP server, so your application does not need to install or manage Puppeteer browsers.
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)
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}`);
See the ScreenshotNeo API documentation for request options. Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status with X-Page-Verdict and X-Billed headers. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots.
Create a free ScreenshotNeo account.
FAQ
Does skipping the download make Puppeteer smaller?
It removes the browser archive from installation. The Puppeteer package and its Node dependencies still install.
Can I use skipDownload with puppeteer-core?
No. puppeteer-core ignores Puppeteer configuration files and environment variables because it is designed for self-managed or remote browsers.
Do I need to reinstall after adding the variable?
Yes. Download options are evaluated during installation, so rerun the install step after changing the variable or configuration.
Which browser version should I install?
Use the supported-browser mapping for your exact Puppeteer release and target platform. Compatibility is release-specific.
Is a system Chrome always compatible?
No. A system browser can work when its version and platform are supported, but verify the mapping instead of assuming interchangeability.


