How to Skip Chromium Download in Puppeteer
Skip Puppeteer’s Chromium download with an environment variable or config, then connect to a browser you manage separately.
Direct answer: Set PUPPETEER_SKIP_DOWNLOAD=true before installing the full puppeteer package, or set skipDownload: true in Puppeteer’s configuration file. Both options stop the installation-time browser download. They do not install, find or configure a browser for runtime.
If your application still launches a browser, provide one separately with puppeteer-core, an explicit executablePath, a supported Chrome channel, or a remote browser connection. Puppeteer documents compatibility guarantees for its bundled browser, so validate any system-browser combination against the Puppeteer version you use. See the official configuration reference, configuration guide and LaunchOptions API.
Choose the right setup
| Approach | Browser download | Who manages the browser? | When to use it |
|---|---|---|---|
puppeteer + skipDownload |
Skipped during installation | Your image, host or deployment process | You need the full package API but already provide Chrome |
puppeteer-core |
Never downloaded automatically | Your application, infrastructure or remote browser | You intentionally manage browser provisioning |
Normal puppeteer installation |
Puppeteer installs its compatible browser | Puppeteer’s browser installer | You want the documented default and simplest pairing |
Option 1: skip the download with an environment variable
The most portable method is to set PUPPETEER_SKIP_DOWNLOAD=true in the environment where the package installation runs.
Linux and macOS
PUPPETEER_SKIP_DOWNLOAD=true npm install puppeteer
Windows PowerShell
$env:PUPPETEER_SKIP_DOWNLOAD = "true"
npm install puppeteer
Windows Command Prompt
set PUPPETEER_SKIP_DOWNLOAD=true
npm install puppeteer
You can also put the variable in your CI or container environment before npm ci. Puppeteer’s configuration reference notes that environment variables can override the corresponding configuration setting. Browser-specific skip-download controls also exist, so check the variables that apply to the browser products enabled by your Puppeteer version.
Option 2: set skipDownload in a configuration file
Create a Puppeteer configuration file in your project and set skipDownload to true.
// puppeteer.config.cjs
/** @type {import('puppeteer').Configuration} */
module.exports = {
skipDownload: true
};
Then install normally:
npm install puppeteer
This setting changes installation behavior only. It does not select a browser executable and does not make a browser available to puppeteer.launch(). Puppeteer configuration files and environment variables are ignored by puppeteer-core.
Changing the setting after installation
Download-related configuration is read by Puppeteer’s installation process. If dependencies are already installed, rerun the package’s postinstall step or reinstall the dependency after changing the setting. A configuration file added after the original install cannot retroactively remove a browser that was already downloaded.
Option 3: use puppeteer-core
puppeteer-core does not download Chrome. It is intended for remote browsers and environments where your application or infrastructure owns browser installation and updates.
npm install puppeteer-core
Do not add skipDownload to a puppeteer-core setup expecting it to control installation. There is no automatic Chrome download in that package, and its configuration files and environment variables are not used.
Make the separately managed browser available at runtime
After skipping the download, choose how Puppeteer will reach a browser.
Launch a known executable
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/usr/bin/google-chrome',
headless: true
});
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
console.log(await page.title());
await browser.close();
})();
Use the real path from your operating system or container image. Keep the path in an environment variable when it differs between development, CI and production:
const browser = await puppeteer.launch({
executablePath: process.env.CHROME_BIN,
headless: true
});
Use a recognized Chrome channel
The launch API supports a Chrome channel for regular system installations in known locations. Treat this as a convenience for selecting an installed browser, not as a compatibility guarantee.
const browser = await puppeteer.launch({
channel: 'chrome',
headless: true
});
Connect to a remote browser
If your platform provides a remote debugging endpoint, connect according to that provider’s endpoint and authentication requirements. The key design point is that browser provisioning and updates happen outside Puppeteer.
Complete runnable examples
Node.js with an explicit executable
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
executablePath: process.env.CHROME_BIN,
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();
}
})();
Install in a CI job
export PUPPETEER_SKIP_DOWNLOAD=true
npm ci
node capture.js
Your CI image must already contain a compatible browser, and CHROME_BIN must point to it if you use executablePath.
Docker pattern
ENV PUPPETEER_SKIP_DOWNLOAD=true
ENV CHROME_BIN=/usr/bin/google-chrome
RUN npm ci
CMD ["node", "capture.js"]
The Docker image still needs to install Chrome or Chromium through its own image build process. The environment variable only prevents Puppeteer’s download.
What happens when installation scripts are blocked?
Package managers can disable dependency install scripts. In that case Puppeteer’s browser download may not run, and a later launch can fail with a browser-not-found message. The documented recovery choices are to allow Puppeteer’s install script or install the browser manually with the Puppeteer browsers command. If you intentionally skip the download, use the same principle: provision a browser in the image or host and point Puppeteer to it.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Could not find Chrome |
The download was skipped or the install script was blocked, and no runtime browser is available. | Install a browser manually, allow the install script, set executablePath, select a supported channel, or connect to a remote browser. |
| The variable appears to do nothing | It was set after installation, misspelled, or applied to a different shell or CI step. | Set it in the same environment as npm install/npm ci, then reinstall or rerun the relevant postinstall step. |
skipDownload is ignored |
The project uses puppeteer-core. |
Remove the setting and manage the browser explicitly; puppeteer-core has no automatic download. |
| Executable launches locally but fails in CI | The path, permissions, OS packages or sandbox settings differ. | Verify the binary exists in the CI image, use an absolute path, and make the browser path an environment variable. |
| Pages behave differently after switching browsers | Puppeteer guarantees compatibility with its bundled browser, while system browsers can differ by version. | Pin and test the browser version used by the deployment, and verify screenshots, navigation and required features. |
Performance, reliability and cost considerations
- Install time and image size: skipping the download can reduce dependency-install work, but your image still includes whatever browser you install separately.
- Cold starts: a prebuilt image with a browser is usually more predictable than downloading one during each deployment.
- Updates: external browser ownership means you must plan browser patching and compatibility checks.
- Reproducibility: pin the browser image or executable version where possible, then run your capture tests after Puppeteer upgrades.
- Compatibility: the bundled browser is Puppeteer’s documented compatibility target. A system browser or remote browser can work, but validate it with your workload.
- Cost: the setting itself has no runtime fee. Infrastructure costs come from the browser environment, build storage, CI time and any remote-browser service you choose.
Or skip the browser setup
If your goal is to obtain screenshots rather than operate Chromium, ScreenshotNeo provides a website screenshot API and MCP server. One request returns a PNG, JPEG, WebP or PDF, so your application does not need to download, patch or launch a browser.
Using 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 failed: ${res.status}`);
require('fs').writeFileSync('shot.webp', Buffer.from(await res.arrayBuffer()));
Cookie and consent banners, newsletter popups and chat widgets are removed before capture. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Does skipping the download make Puppeteer smaller at runtime?
It removes Puppeteer’s installation download. Your runtime still needs a browser if your code launches one.
Can I use PUPPETEER_SKIP_DOWNLOAD with puppeteer-core?
It is unnecessary. puppeteer-core does not download Chrome and ignores Puppeteer configuration files and environment variables.
Which browser path should I use?
Use the absolute path to the browser installed in the target environment, or use a supported Chrome channel. Verify the chosen browser with your Puppeteer version.
Should production always skip Chromium downloads?
Only when your deployment process deliberately provisions and updates a compatible browser. Otherwise, the normal Puppeteer installation is the simpler documented setup.
Does ScreenshotNeo require Puppeteer?
No. ScreenshotNeo is accessed through its API or MCP server, so your application can request screenshots without managing a local Chromium installation.


