· Troubleshooting · By Simon Chiu

Puppeteer: Failed to Launch the Browser Process (Fixed)

Failed to launch the browser process in Puppeteer, step by step: we hit four different launch errors in one Docker image on Puppeteer 25 and fixed each one.

Error: Failed to launch the browser process is a wrapper. Puppeteer started Chrome, Chrome exited, and Puppeteer printed Chrome's stderr under the message. The real cause is in that stderr block, and it is almost always one of three things on Linux: a missing shared library (Code: 127), Chrome running as root with the sandbox on (Code: 1), or a sandbox the container does not allow (No usable sandbox!). Read the line under stderr: and jump to the matching section below.

This is a spoke of our Puppeteer screenshot guide. We started from a bare Debian slim image and fixed one error at a time. Each error below is copied from that run.

Tested on 2026-10-18 with Docker (OrbStack on macOS, node:22-bookworm-slim linux/amd64, Debian 12.15), Node 22, [email protected] (Chrome 155.0.8059.79). Version checks also ran [email protected] and @24.10.0.

The test script

import puppeteer from 'puppeteer';

const args = process.env.NO_SANDBOX ? ['--no-sandbox'] : [];
const browser = await puppeteer.launch({ args });
try {
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({ path: '/tmp/example.png' });
  console.log('OK', await browser.version());
} finally {
  await browser.close();
}

Stage 0: "Could not find Chrome" after a clean install

The first surprise came before any launch. npm i [email protected] exited with code 0, yet the script failed with:

Error: Could not find Chrome (ver. 155.0.8059.79). This can occur if either
 1. you did not perform an installation before running the script (e.g. `npx puppeteer browsers install chrome`) or
 2. your cache path is incorrectly configured (which is: /root/.cache/puppeteer).

Running the install command by hand showed the reason:

Error: All providers failed for chrome 155.0.8059.79:
  - DefaultProvider: Extraction failed: no zip archiver is available. Install `unzip` (or `tar.exe`/Powershell on Windows), or add the optional `yauzl` dependency.

Slim Debian images ship without unzip. Fix: apt-get install -y unzip before npm install. Do not trust a green npm install as proof that Chrome is there; check the path with npx puppeteer browsers list in the build.

Stage 1: Code 127, a missing shared library

With unzip added and Chrome downloaded, launch failed with:

Error: Failed to launch the browser process:  Code: 127

stderr:
/root/.cache/puppeteer/chrome/linux-155.0.8059.79/chrome-linux64/chrome: error while loading shared libraries: libglib-2.0.so.0: cannot open shared object file: No such file or directory

Many people search for this with libnss3.so in the message. Which library appears first depends on the image, because the loader stops at the first one it cannot find. ldd shows the full list:

ldd ~/.cache/puppeteer/chrome/linux-*/chrome-linux64/chrome | grep 'not found'

On the slim image that printed libglib-2.0.so.0, libgobject-2.0.so.0, libnspr4.so, libnss3.so, libnssutil3.so, libsmime3.so, libgio-2.0.so.0, libatk-1.0.so.0, libatk-bridge-2.0.so.0, libdbus-1.so.3, libcups.so.2, libexpat.so.1, libxcb.so.1, libxkbcommon.so.0, libasound.so.2, libgbm.so.1, libX11.so.6, libXext.so.6, libcairo.so.2, libpango-1.0.so.0 and more. Installing them one error at a time takes many rebuilds.

Fix: let Puppeteer install the system packages. It must run as root, on Debian or Ubuntu:

npx puppeteer browsers install chrome --install-deps

Stage 2: Code 1, running as root

With the libraries in place, the next launch failed with a different code:

Error: Failed to launch the browser process:  Code: 1

stderr:
ERROR:content/browser/zygote_host/zygote_host_impl_linux.cc:103] Running as root without --no-sandbox is not supported. See https://crbug.com/638180.

Docker containers run as root unless the image says otherwise. Chrome refuses to start its sandbox as root. Passing --no-sandbox made the launch succeed (OK Chrome/155.0.8059.79), and that is the line most answers stop at. Read the Chromium sandbox entry before you ship it: without the sandbox, the container is the only barrier between a hostile page and your process.

Stage 3: "No usable sandbox!" as a non-root user

The safer move is a non-root user. As the image's node user, with the sandbox on, Chrome crashed with signal 6:

Error: Failed to launch the browser process:  Code: null

stderr:
FATAL:content/browser/zygote_host/zygote_host_impl_linux.cc:130] No usable sandbox! If you are running on Ubuntu 23.10+ or another Linux distro that has disabled unprivileged user namespaces with AppArmor, see ...

Chrome's sandbox needs user namespaces, and Docker's default seccomp profile blocks the calls it uses. We re-ran the same container with --security-opt seccomp=unconfined and the non-root launch worked with the sandbox on. In production, use a seccomp profile that allows only what Chrome needs instead of turning seccomp off. On an Ubuntu 23.10+ host outside Docker, the same message comes from AppArmor's user-namespace rules, and the fix is an AppArmor profile for the Chrome binary.

A Dockerfile that passes all four stages

FROM node:22-bookworm-slim
RUN apt-get update \
 && apt-get install -y --no-install-recommends unzip ca-certificates \
 && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY package*.json ./
RUN npm ci \
 && npx puppeteer browsers install chrome --install-deps \
 && mkdir -p /home/node/.cache \
 && cp -r /root/.cache/puppeteer /home/node/.cache/ \
 && chown -R node:node /home/node/.cache /app
COPY . .
USER node
CMD ["node", "shot.mjs"]

Run it with a seccomp profile that permits the sandbox. We tested the steps of this file inside a running container, not this exact file as a build.

Version matrix

Environment puppeteer 22.15.0 puppeteer 24.10.0 puppeteer 25.14.0
Chrome version downloaded 127.0.6533.88 137.0.7151.55 155.0.8059.79
npm i on slim image without unzip Chrome extracted Chrome extracted exit 0, no Chrome
Missing libraries not re-tested not re-tested Code 127
Root, sandbox on (libraries installed) not re-tested not re-tested Code 1, Running as root
Non-root, default seccomp not re-tested not re-tested No usable sandbox!
Non-root, seccomp unconfined not re-tested not re-tested OK

We ran the install row on all three versions and the launch rows on 25.14.0 only.

Symptom, cause, fix

stderr shows Cause Fix
Could not find Chrome (ver. ...) Download or extraction failed Install unzip; run npx puppeteer browsers install chrome
Code: 127 + error while loading shared libraries System libraries missing --install-deps, or the full apt list
Code: 1 + Running as root without --no-sandbox Root user, sandbox on Run as non-root, or --no-sandbox for trusted pages
No usable sandbox! Seccomp or AppArmor blocks user namespaces Seccomp profile or AppArmor rule; --no-sandbox as last resort
Missing X server or $DISPLAY headless: false on a server Keep headless, or run under Xvfb
cache path is incorrectly configured Chrome installed as one user, run as another Copy the cache or set PUPPETEER_CACHE_DIR
Works on amd64, fails on arm64 Linux No Chrome for Testing build for linux arm64 Use an amd64 image, or a distro Chromium with executablePath

We reproduced the first four rows and the cache-path message. The $DISPLAY and arm64 rows come from the Puppeteer troubleshooting docs; we did not reproduce them for this page.

The same capture without a local browser

If Chrome exists on your server only to take screenshots, an API removes this whole page of setup. The RenderScreenshot API runs the browser for you; your container needs Node and an API key. With the Node SDK:

import { writeFile } from 'node:fs/promises';
import { Client, TakeOptions } from 'renderscreenshot';

const client = new Client(process.env.RS_API_KEY);
const image = await client.take(TakeOptions.url('https://example.com'));
await writeFile('example.png', image);

We did not call the live API for this page. The migration guide from Puppeteer maps goto and screenshot options to API parameters. For Selenium's version of the same crash, see DevToolsActivePort file doesn't exist, and for the failures that come after launch, our headless Chrome production failures write-up. Get a free API key to compare.

Related in this topic