Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
Chrome

How to Fix “Puppeteer Could Not Find Chrome” in Docker

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The error means Puppeteer cannot resolve a browser binary inside the container. Install a compatible browser during the image build and keep its cache available to the runtime user, or point Puppeteer at the real path of a system Chrome/Chromium installation. If the browser is found but will not start, troubleshoot Linux libraries and sandbox permissions separately.

What the error actually means

A successful npm install puppeteer does not guarantee that Chrome exists in the final container. Puppeteer’s package and its browser are separate at deployment time: an install policy can skip the postinstall download, a multi-stage build can discard the browser cache, or the build and runtime users can use different home directories. With puppeteer-core, no browser is downloaded at all; your application must install and select one.

First identify the package and version in your lockfile and in the image:

npm ls puppeteer puppeteer-core
node -p "require('puppeteer/package.json').version" 2>/dev/null || true
node -p "require('puppeteer-core/package.json').version" 2>/dev/null || true

The familiar message “Could not find Chrome (ver. …)” is normally a browser-resolution problem. A later error mentioning process spawning, missing libraries or sandboxing is a launch problem and needs a different fix.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose a browser-management strategy

Strategy What you install What your code must do Best fit
Puppeteer-managed browser The browser downloaded by Puppeteer, normally Chrome for Testing Use the matching Puppeteer defaults; keep the cache in the runtime image Projects wanting Puppeteer’s expected browser version
System-managed browser Chrome or Chromium installed by the Dockerfile or base image Pass its in-container path with executablePath (or a standard channel) Images that own browser updates or use a separately managed browser
Official Puppeteer image Chrome for Testing, dependencies and a pre-installed Puppeteer version Pin compatible tags and provide the required capability and init process Teams that prefer a maintained browser-ready base

Do not mix assumptions. Installing a Debian Chrome package does not make Puppeteer’s downloaded browser appear in ~/.cache/puppeteer, and installing puppeteer-core does not trigger any browser download.

Fix 1: install Puppeteer’s browser in the image build

Allow the install script, or run the documented recovery command

Package-manager settings such as ignored scripts can leave the Node package present while its browser download never runs. After dependencies are installed, explicitly install the browser in the same application directory:

RUN npx puppeteer browsers install

For a Debian/Ubuntu-style custom image, the essential pattern is:

FROM node:22-bookworm-slim
WORKDIR /app

COPY package*.json ./
RUN npm ci
# Required when install scripts were disabled or the download did not run:
RUN npx puppeteer browsers install

COPY . .
CMD ["node", "server.js"]

If your package manager is configured to block lifecycle scripts, either permit Puppeteer’s postinstall script for this build or retain the explicit npx puppeteer browsers install step. Run it after the Puppeteer dependency and its configuration file are available.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep the browser cache in the final stage

Puppeteer stores downloaded browsers under the installing account’s home directory by default, commonly ~/.cache/puppeteer. In a multi-stage Dockerfile, installing the browser only in a builder stage is ineffective unless that directory is copied into the final stage. A reliable approach is to choose a shared cache path and use it for both build and runtime:

FROM node:22-bookworm-slim AS build
WORKDIR /app
ENV PUPPETEER_CACHE_DIR=/opt/puppeteer-cache
COPY package*.json ./
RUN npm ci
RUN npx puppeteer browsers install
COPY . .

FROM node:22-bookworm-slim
WORKDIR /app
ENV NODE_ENV=production
ENV PUPPETEER_CACHE_DIR=/opt/puppeteer-cache
COPY --from=build /app /app
COPY --from=build /opt/puppeteer-cache /opt/puppeteer-cache
CMD ["node", "server.js"]

Use the same effective home directory, cache variable and Puppeteer configuration at build and runtime. If you switch from root during the image build to a non-root user at runtime, verify that the runtime user can read and execute the copied files.

Verify the install before starting the service

RUN npx puppeteer browsers list
RUN find /opt/puppeteer-cache -maxdepth 4 -type f -name 'chrome' -o -name 'chrome-headless-shell' | head

The exact executable name and directory vary by Puppeteer version. The important checks are that a browser is listed, the directory is in the final image, and the runtime user can access it.

Fix 2: use system Chrome or Chromium explicitly

When your Dockerfile deliberately installs a system browser, locate the binary inside that image instead of guessing a host path:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
which google-chrome || true
which chromium || true
which chromium-browser || true
find /usr/bin /usr/local/bin -maxdepth 2 -type f ( -name 'google-chrome*' -o -name 'chromium*' ) 2>/dev/null

Then pass the discovered path to puppeteer.launch:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    executablePath: process.env.CHROME_PATH || '/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();
})();

Puppeteer’s documented manual-management approach is to call puppeteer.launch with an explicit executablePath, or a channel when the browser is installed in a standard location. The path must exist inside the container, not only on your development machine. Validate that the system browser version is compatible with the Puppeteer version you installed.

Fix 3: use the official Puppeteer Docker image

The official image includes Chrome for Testing, required dependencies and a pre-installed Puppeteer version. Its tags follow Puppeteer versions, so pin the image tag rather than relying on a mutable latest tag when reproducibility matters. Keep your application’s Puppeteer dependency aligned with that image tag.

The Docker guide describes the image as intended for sandboxed browser execution. Running it therefore requires the SYS_ADMIN capability. It also recommends an init process, supplied with Docker’s --init option or a custom entrypoint, so child browser processes are reaped correctly:

docker run --init --cap-add=SYS_ADMIN your-image

Do not add --no-sandbox automatically. Removing the sandbox changes the security model; first provide the capability and user setup expected by the image and your deployment environment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Separate “browser missing” from “browser cannot launch”

Confirm the file exists and is executable

test -x "$CHROME_PATH" && echo "executable" || echo "missing or not executable"
ls -l "$CHROME_PATH"
"$CHROME_PATH" --version

If Puppeteer reports that Chrome cannot be found, fix the path, cache or image contents. If it reports that a process could not spawn, continue with dependency and permission checks.

Find missing shared libraries

Linux can contain the browser file while still failing to start because a shared library is absent. Run the dependency check against the actual binary:

ldd "$CHROME_PATH" | grep not

Install the libraries reported as missing using the package manager for your base distribution, then rebuild the image. Keep this diagnosis separate from Puppeteer’s browser-resolution settings: adding an executablePath cannot repair a missing system library.

Check user, permissions and sandbox context

  • Print the effective user and home directory with id and echo "$HOME".
  • Ensure the runtime user can read the browser cache and execute the binary.
  • Check that a read-only filesystem, restrictive noexec mount or security profile is not blocking execution.
  • For the official image, provide SYS_ADMIN and an init process as documented; do not assume local Docker privileges exist in a hosted runner.

Common Docker failure modes and fixes

Symptom Likely cause Fix
Could not find Chrome (ver. …) Download skipped or browser cache absent Run npx puppeteer browsers install after npm ci; include the cache in the final image
Works as root during build, fails as app user Different HOME, cache path or permissions Set PUPPETEER_CACHE_DIR consistently and grant read/execute access
System Chrome installed but Puppeteer still searches its cache No explicit browser selection Set executablePath to the in-container binary or use a supported channel
spawn, “error while loading shared libraries” or immediate exit Browser exists but dependencies are missing Run ldd chrome | grep not and install the missing libraries
Browser starts, then hangs or leaves zombies No init process managing child processes Run the container with --init or use an entrypoint that performs equivalent reaping
Different result after rebuilding with latest Mutable image and application versions drifted Pin a Puppeteer image tag and matching application dependency

A repeatable diagnostic checklist

  1. Read package.json and the lockfile; distinguish puppeteer from puppeteer-core and record the version.
  2. Inspect package-manager policy for ignored lifecycle scripts.
  3. In the Docker build, run npx puppeteer browsers install and npx puppeteer browsers list.
  4. Set and record one cache location, such as PUPPETEER_CACHE_DIR=/opt/puppeteer-cache, for both build and runtime.
  5. In multi-stage builds, copy that cache into the final stage.
  6. Run the container as the same user your service uses and verify HOME, permissions and executable access.
  7. If using system Chrome, discover its path inside the image and pass executablePath.
  8. If resolution succeeds but launch fails, run ldd, inspect sandbox capability and add an init process.
  9. Rebuild without stale layers when changing browser-install commands, then test a minimal page navigation before deploying the full workload.

Performance, reliability and image-size considerations

  • A Puppeteer-managed browser makes the application’s expected browser version explicit, but the cache increases image-build time and image size.
  • A system browser can fit an organization’s patching policy, yet upgrades must be tested against the Puppeteer version and your page behavior.
  • Copying a browser cache between stages avoids downloading again, but only if architecture, distribution and runtime user match.
  • Pinning both the Node base image and Puppeteer-compatible browser image improves repeatability; rebuilding periodically is still necessary for security updates.
  • Run a smoke test in CI that launches the browser, opens a known URL, takes a screenshot and closes cleanly. This catches missing files, libraries and permissions before production.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your application only needs reliable website screenshots, ScreenshotNeo provides a hosted API instead of requiring Chrome in your Docker image. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

One GET request returns PNG, JPEG, WebP or PDF:

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

See the ScreenshotNeo documentation for all options, including full-page lazy-image loading, CSS-selector element capture, dark mode, device presets, arbitrary viewports, retina scale, PDF paper and page ranges, custom CSS/JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting and the OpenAPI specification. An MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.

There is a free allowance of 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it without adding a card.

FAQ

Does installing Chromium with apt automatically fix Puppeteer?

No. Puppeteer may still look for its managed browser. Discover the binary inside the image and provide its path through executablePath, or install Puppeteer’s managed browser instead.

Can I install the browser only when the container starts?

You can, but it makes startup depend on network access and produces less predictable deployments. Installing during the image build gives you a testable, reproducible artifact.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does puppeteer-core behave differently?

puppeteer-core does not download Chrome. Your image and application must install a compatible browser and select it explicitly.

Best Value
Docker Container Linux Devops Programming Coding T-Shirt
  • Docker, Docker Swarm, Docker Compose, Programmer, Developer, Coding, Programming, Software Engineer, Code, DevOps, Deploy, Deployment, Kubernetes, Salt, Puppet, Chef, Terraform, Container, AWS, Azure, Cloud, Geek, Funny, Computer, Software, Tech, IT
  • Integration, Scrum, Compile, Compilation, Science, Bug, Debug, Python, Linux, Java, Javascript, Scala, Dotnet, Kotlin
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

Is --no-sandbox the universal Docker fix?

No. It is a security trade-off, not a browser-discovery repair. Prefer the sandbox-capable setup and capabilities required by your chosen image; use a reduced-sandbox configuration only after evaluating your deployment’s security requirements.

Frequently Asked Questions

Does installing Chromium with apt automatically fix Puppeteer?

No. Puppeteer may still look for its managed browser. Discover the binary inside the image and provide its path through executablePath, or install Puppeteer’s managed browser instead.

Can I install the browser only when the container starts?

You can, but startup then depends on network access and is less reproducible. Installing during the image build creates a testable deployment artifact.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does puppeteer-core behave differently?

puppeteer-core does not download Chrome. Your image and application must install a compatible browser and select it explicitly.

Is –no-sandbox the universal Docker fix?

No. It is a security trade-off, not a browser-discovery repair. Prefer the sandbox-capable setup and required container capabilities.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.