ScreenshotNeo

BlogHow-to

How to Install Chrome with puppeteer/browsers

Install Chrome for Puppeteer, choose a browser channel or version, configure caches, and fix missing-browser errors in local and CI environments.

By the ScreenshotNeo team1 October 20268 min read

Direct answer: install puppeteer when you want Puppeteer to download and manage a compatible Chrome for Testing browser:

npm i puppeteer

Then launch Puppeteer normally:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
console.log(await page.title());
await browser.close();

Puppeteer normally downloads a compatible Chrome for Testing binary during installation. If your package manager blocked install scripts, install the browser explicitly with npx puppeteer browsers install. The official installation guide is at pptr.dev/guides/installation.

Choose the right installation method

Requirement Use What happens
Let Puppeteer manage Chrome puppeteer Install scripts download a compatible Chrome for Testing browser.
Your organisation already supplies Chrome or Chromium puppeteer-core No browser is downloaded. You provide executablePath, channel, or a remote browser connection.
Pin a release for reproducible builds @puppeteer/browsers Install a stable channel, milestone, or exact Chrome version.
Run on a minimal Linux image puppeteer browsers install chrome --install-deps Attempts to install required Linux dependencies; root privileges are required.

1. Install Puppeteer and its managed Chrome

npm

npm init -y
npm i puppeteer

Yarn

yarn add puppeteer

pnpm

pnpm add puppeteer

After installation, verify that the browser can launch:

node --input-type=module <<'EOF'
import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ headless: true });
const version = await browser.version();
console.log(version);
await browser.close();
EOF

If the command prints a Chrome version, the Puppeteer-managed browser is available.

2. Install Chrome manually with puppeteer/browsers

The puppeteer browsers command installs browser binaries independently of your application code.

Install the default Chrome for Testing build

npx puppeteer browsers install chrome

In many projects this is equivalent to:

npx puppeteer browsers install

Install the stable channel

npx @puppeteer/browsers install chrome@stable

Install a Chrome milestone

npx @puppeteer/browsers install chrome@120

Install an exact version

npx @puppeteer/browsers install chrome@120.0.6099.109

Pinning an exact version improves repeatability, but you must update it deliberately for security fixes and compatibility. The browser-management commands are documented in the Puppeteer browsers package README.

3. Launch a separately installed Chrome

Use puppeteer-core when Chrome is installed by your operating system, a container image, your CI environment, or a remote browser service.

npm i puppeteer-core

Use an executable path

import puppeteer from 'puppeteer-core';

const browser = await puppeteer.launch({
  headless: true,
  executablePath: '/usr/bin/google-chrome'
});

const page = await browser.newPage();
await page.goto('https://example.com');
await browser.close();

Typical paths vary by operating system and installation method. Do not hard-code a path copied from another machine without checking it with which google-chrome, which chromium, or your platform’s application search.

Use a browser channel

When a supported system browser is installed, you can identify it by channel:

import puppeteer from 'puppeteer-core';

const browser = await puppeteer.launch({
  headless: true,
  channel: 'chrome'
});

Use channel when the browser is installed in a standard location. Use executablePath when you need an exact binary.

4. Install Linux dependencies

Chrome requires shared libraries and other system packages on many minimal Linux images. On Ubuntu or Debian, Puppeteer can attempt to install them:

sudo npx puppeteer browsers install chrome --install-deps

The dependency step requires root privileges and may not be appropriate for a locked-down CI runner. In Docker, install OS packages in the image build stage, then run the browser installation as the non-root application user when possible.

If you see errors mentioning libnss3.so, libatk-1.0.so.0, sandboxing, or missing fonts, the browser binary may be present while its operating-system dependencies are not.

5. Control the Puppeteer browser cache

For installations since Puppeteer v19, downloaded browsers normally live under ~/.cache/puppeteer. The cache must be available in the same build or runtime environment that launches the browser.

Set the cache directory with an environment variable

export PUPPETEER_CACHE_DIR=/opt/puppeteer-cache
npx puppeteer browsers install chrome

Set it in Puppeteer configuration

// .puppeteerrc.cjs
/** @type {import('puppeteer').Configuration} */
module.exports = {
  cacheDirectory: '/opt/puppeteer-cache'
};

Configuration files and environment variables can override defaults. Check the active configuration before changing application code. See the Puppeteer configuration API.

CI cache checklist

  • Use the same cache path during installation and execution.
  • Persist the cache between jobs if your CI system supports dependency caching.
  • Make sure the runtime user can read and execute the cached browser.
  • Invalidate the cache when changing the pinned browser version.
  • Do not assume a cache on one machine exists inside a new container.

6. Complete runnable examples

JavaScript with managed Chrome

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
  headless: true,
  args: ['--disable-dev-shm-usage']
});

try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 });
  await page.goto('https://example.com', { waitUntil: 'networkidle2', timeout: 60000 });
  await page.screenshot({ path: 'example.png', fullPage: true });
} finally {
  await browser.close();
}

JavaScript with a pinned, separately installed browser

import puppeteer from 'puppeteer-core';

const browser = await puppeteer.launch({
  headless: true,
  executablePath: process.env.CHROME_BIN || '/usr/bin/google-chrome'
});

const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
console.log(await page.title());
await browser.close();

cURL, Python, and Node.js alternatives

If your goal is a screenshot rather than browser automation, a screenshot API avoids installing Chrome locally. ScreenshotNeo provides a single GET request and documents the options at screenshotneo.com/docs/.

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}`);

7. Configuration choices that affect installation

Choice Effect Best use
Managed puppeteer Puppeteer selects and downloads a compatible browser. Local development and straightforward deployments.
puppeteer-core plus executablePath Your application controls the exact binary. Enterprise images, OS-managed Chrome, and pinned builds.
Stable channel Tracks the stable Chrome line. Applications that accept regular browser updates.
Milestone Selects a major Chrome version. Testing against a browser generation.
Exact version Locks a specific browser release. Reproducible CI and regression tests.
Custom cache Moves downloaded binaries out of the default home directory. Containers, build workers, and shared caches.
--install-deps Attempts to add Linux runtime dependencies. Debian or Ubuntu hosts where you have root access.

8. Troubleshooting missing Chrome and failed launches

“Could not find Chrome” or “Cannot find browser”

Cause: the install script was skipped, the browser was installed into another cache, or the runtime uses a different user or container.

Fix:

  1. Run npx puppeteer browsers install from the application directory.
  2. Check PUPPETEER_CACHE_DIR and any Puppeteer configuration file.
  3. Run the install and launch steps with the same user and environment.
  4. If using puppeteer-core, provide a valid executablePath or channel.

Package installation succeeds but no browser is downloaded

Cause: npm, Yarn, pnpm, or a security policy disabled lifecycle scripts.

Fix: run npx puppeteer browsers install explicitly in the build step. Do not rely on an install script that your package manager intentionally blocks.

“Failed to launch the browser process” on Linux

Cause: missing shared libraries, sandbox restrictions, or an incompatible container image.

Fix: install the required OS packages with npx puppeteer browsers install chrome --install-deps where supported, or add the dependencies to your image. Review the first missing library in the error output before adding launch flags.

Sandbox errors in containers

Cause: the container user or kernel configuration does not allow Chrome’s sandbox.

Fix: run Chrome as a properly configured non-root user and enable the container’s sandbox support. Only use --no-sandbox when you understand the security trade-off and your deployment policy permits it.

The browser works locally but fails in CI

Cause: CI has a different OS, architecture, user, cache path, dependency set, or network policy.

Fix: print the selected executable path, persist the configured cache, install Linux dependencies in the image, and pin a browser version. Keep installation and execution in the same job or artifact.

A custom executable path points to the wrong binary

Cause: the path references an old Chrome installation, a wrapper script, or Chromium when your test requires Chrome.

Fix: verify the path with the operating system, run the binary’s version command, and remove the override temporarily to determine whether Puppeteer’s managed browser works.

Downloads fail behind a proxy

Cause: the browser download cannot reach its host from the build network.

Fix: configure the build environment’s approved proxy or mirror, or download the browser in a networked build stage and carry the cache into the runtime image.

9. Performance, reliability, and cost

Performance

  • Persist the browser cache so every deployment does not download Chrome again.
  • Reuse one browser process for multiple pages when isolation requirements allow it.
  • Pinning a version avoids repeated dependency resolution and unexpected browser changes.
  • Keep the browser and application in the same region or container when startup latency matters.
  • Use an explicit timeout and close pages and browsers in finally blocks.

Reliability

  • Record the Puppeteer version, Chrome version, operating system, architecture, and cache directory in build logs.
  • Test a clean install periodically instead of relying only on a warm cache.
  • Use a separate browser installation step so application dependency installation failures are easy to diagnose.
  • Keep browser upgrades deliberate; a new Chrome milestone can change rendering, permissions, or automation behavior.

Cost

The npm package is free to install, but browser downloads consume build time, storage, and network bandwidth. A self-managed browser also carries the maintenance cost of OS libraries, security updates, image rebuilds, and CI cache storage.

Or skip the browser setup

For screenshot jobs, ScreenshotNeo provides a website screenshot API and MCP server. Cookie and consent banners are accepted before capture, then more than 60 known consent platforms, newsletter popups, and chat widgets are removed. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the result with X-Page-Verdict and X-Billed headers.

The same API supports full-page shots, CSS element capture, dark mode, device presets, custom viewports, retina scale, PDFs, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous jobs, webhooks, bulk capture, and usage reporting. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

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

There is a free plan with 1,000 screenshots per month and no card required. Paid plans start at $5 for 3,000 screenshots, and every feature is available on every plan. Create a free ScreenshotNeo account.

FAQ

Does npm i puppeteer always install Chrome?

It normally downloads a compatible Chrome for Testing browser, but package-manager policies can block lifecycle scripts. Run npx puppeteer browsers install when the browser is missing.

Can I use Google Chrome already installed on my computer?

Yes. Install puppeteer-core and launch with channel: 'chrome' or an explicit executablePath.

Where does Puppeteer store downloaded Chrome?

Since Puppeteer v19, the normal cache is ~/.cache/puppeteer. Set PUPPETEER_CACHE_DIR or cacheDirectory when your environment needs another location.

Should CI use stable or an exact Chrome version?

Use stable when regular browser updates are acceptable. Use a milestone or exact version when reproducibility and controlled upgrades matter more.

Do I need Chrome to capture a screenshot?

Not if you use a hosted screenshot API such as ScreenshotNeo. A single request can return an image or PDF without installing Puppeteer or Chrome in your project.