ScreenshotNeo

BlogHow-to

Puppeteer Screenshot Test Fails on Linux: Missing Dependencies Fix

Fix Puppeteer screenshot failures on Linux by identifying missing Chrome libraries, installing the right packages, and separating dependency errors from browser, sandbox, and container problems.

By the ScreenshotNeo team4 October 20269 min read

If a Puppeteer screenshot test fails on Linux, first identify the exact Chrome executable Puppeteer launches, then run ldd on it and look for libraries marked not found. Install the corresponding runtime packages for your distribution and release. If no browser executable exists, check whether install scripts were blocked; if the error says No usable sandbox!, investigate sandbox or AppArmor configuration separately. These are different failure modes and need different fixes.

This guide focuses on Puppeteer’s downloaded Chrome for Testing. Commands and package names can vary by Puppeteer version and Linux release. Check the requirements and troubleshooting pages for your installed version: Puppeteer troubleshooting, system requirements, and installation.

1. Identify the failure before changing the host

Keep the complete launch error from the test output. Common clues include a missing shared library, an executable that does not exist, a sandbox failure, or a profile-directory permission problem. Do not treat every browser launch failure as a missing-dependency error.

Ask Puppeteer which executable it is configured to launch. In a small diagnostic script using Puppeteer’s usual API:

const puppeteer = require('puppeteer');
console.log(puppeteer.executablePath());

If your test sets executablePath in launch options, inspect that value instead. Run diagnostics against that actual binary, not an unrelated system Chrome. For example:

CHROME="$(node -e "console.log(require('puppeteer').executablePath())")"
printf 'Chrome executable: %s\n' "$CHROME"
test -x "$CHROME" || { echo 'Executable is missing or not executable'; exit 1; }
ldd "$CHROME" | grep 'not found' || true

The ldd command is useful on Linux because unresolved shared libraries appear as not found. If it prints no missing libraries, continue to the browser-installation, sandbox, and environment checks below. An empty result does not prove that every possible launch prerequisite is correct.

2. Install the missing Linux libraries

Install the OS packages that provide the specific libraries reported by ldd. Package names differ across distributions and releases. On Debian or Ubuntu, Puppeteer’s troubleshooting guide lists common dependencies such as libnss3, libatk-bridge2.0-0, libgtk-3-0, libgbm1, libasound2, libx11-xcb1, libxcomposite1, libxdamage1, libxrandr2, libxss1, libxtst6, and fonts-liberation. Consult the current upstream list for the full set and for CentOS-specific guidance: Puppeteer’s Linux dependency instructions.

For a Debian or Ubuntu image, a package installation step may look like this, but verify every package against the base image release and the missing libraries reported on that image:

apt-get update
apt-get install -y --no-install-recommends \
  libnss3 libatk-bridge2.0-0 libgtk-3-0 libgbm1 libasound2 \
  libx11-xcb1 libxcomposite1 libxdamage1 libxrandr2 \
  libxss1 libxtst6 fonts-liberation

This is a starting example, not a universal package manifest. A library name is not always the package name, and package names can change between OS releases. Use your distribution’s package search or file-to-package lookup to map the reported library to its provider. Then rerun ldd after installation.

3. Use Puppeteer’s dependency installer on supported hosts

For Chrome on Ubuntu or Debian, Puppeteer documents an installer option that can install browser dependencies:

sudo npx puppeteer browsers install chrome --install-deps

This path requires root privileges and is specifically documented for Ubuntu and Debian. It is not a universal Linux command. In locked-down build environments, you may need to add the required OS packages to the image instead, so builds remain reproducible and do not need elevated privileges at runtime. See the Puppeteer browsers API documentation.

4. Check whether Puppeteer downloaded a browser

Puppeteer normally downloads a compatible Chrome for Testing browser during installation. A project’s package-manager policy may block install scripts, leaving the Puppeteer package present while its expected browser is absent. That produces a different problem from missing Chrome libraries.

Check that the executable path exists. If the browser was not downloaded, run the browser installation command for your package manager:

# npm / npx
npx puppeteer browsers install

# Yarn
 yarn puppeteer browsers install

# pnpm
pnpm exec puppeteer browsers install

# Bun
bunx puppeteer browsers install

Use the command supported by your project’s package manager and Puppeteer version. The official installation guide describes browser downloads and package-manager considerations: Puppeteer installation. Puppeteer’s guide describes Linux browser downloads as approximately 282 MB, so account for that transfer and storage in fresh CI jobs or restricted build networks.

5. Separate sandbox failures from dependency failures

An error such as No usable sandbox! points to sandbox setup. Installing more shared libraries will not necessarily fix it. Puppeteer strongly discourages launching Chrome with --no-sandbox; disabling the browser sandbox changes its security boundary and should not be used as a routine CI fix.

Configure a suitable sandbox for the host and user that run Chrome. On Ubuntu 23.10 and later, an AppArmor profile can block user namespaces for Puppeteer-downloaded Chrome for Testing. Follow Puppeteer’s documented AppArmor guidance for the specific host and browser binary: Puppeteer sandbox and AppArmor troubleshooting. If the executable is system Chrome rather than Puppeteer’s downloaded browser, confirm which binary the profile applies to.

6. Account for Docker, CI, Alpine, and architecture

Docker and CI

Install Chrome’s required shared libraries in the image that runs the test, not only on a developer workstation or in a build stage that is discarded. Make the Chrome profile directory writable by the runtime user. If tests run as a non-root user, verify its home or configured user-data directory exists and permits writes. A profile permission error is distinct from an unresolved shared library.

For reproducible builds, pin the base image and package installation process, install the Puppeteer package and its browser in a controlled build step, and run the test under the same user and filesystem permissions used in CI. When debugging, print the executable path, run ldd there, and preserve the full browser launch error in CI logs.

Alpine Linux

Do not assume that a Debian or Ubuntu package list applies to Alpine. Puppeteer’s troubleshooting guide says Chrome is not supported out of the box on Alpine and points readers to system package requirements. Check the requirements for your Puppeteer and browser versions, and verify the specific binary and libraries on your Alpine release before choosing a compatibility approach.

Version and architecture checks

Current Puppeteer requirements specify Node.js 22.12 or later and list Chrome for Testing Linux support on Debian/Ubuntu and openSUSE/Fedora for x64 and arm64. Those are version-sensitive requirements: check the documentation for the Puppeteer version in your lockfile before applying them to an older project. See Puppeteer system requirements.

7. A repeatable diagnosis and fix

  1. Save the complete browser launch error from the failing screenshot test.
  2. Print the configured executable path and verify the file exists and is executable.
  3. Run ldd on that exact Chrome binary. Map every not found entry to a package for the current OS release.
  4. Install only the required packages, or use Puppeteer’s documented --install-deps option on a supported Debian or Ubuntu host with root access.
  5. Rerun ldd, then run the screenshot test as the same user and in the same container or CI image.
  6. If there are no missing libraries, check whether the browser downloaded, whether its profile directory is writable, and whether the error points to sandbox or AppArmor configuration.
  7. Record the Puppeteer version, Node version, OS release, architecture, and browser path with the failure so later updates can be diagnosed against the same environment.

8. Troubleshooting common errors

Symptom Likely cause What to do
error while loading shared libraries or ldd shows not found A runtime library required by the launched Chrome binary is missing. Map the missing library to the package for this Linux release, install it in the runtime image, and rerun ldd.
Executable path does not exist The browser download was skipped, failed, or Puppeteer points to a different path. Check install-script policy and configured executablePath; install the browser with the documented Puppeteer browser command.
No usable sandbox! Host sandbox configuration or, on affected Ubuntu systems, AppArmor blocking user namespaces. Follow Puppeteer’s host-specific sandbox and AppArmor guidance. Avoid treating this as a library problem or routinely using --no-sandbox.
Chrome starts locally but fails in Docker or CI The runtime image lacks dependencies, uses another user, has a read-only profile directory, or differs in OS/architecture. Run the same executable diagnostics inside the failing image and as its runtime user; install packages there and provide writable profile storage.
Debian package cannot be found The package name differs on that release or the image’s package indexes are stale. Refresh package indexes and look up the provider for the missing library on that exact release; do not copy a package name from another distribution.
Alpine-specific launch failure Chrome is not supported out of the box there, and compatibility differs from Debian-based images. Review Puppeteer’s Alpine and system-requirements guidance for the exact versions before changing packages or browser binaries.
No missing libraries, but launch still fails The problem lies elsewhere: browser download, permissions, sandbox, incompatible versions, or runtime configuration. Use the full error to select the next check. Confirm the executable, user-data directory permissions, host policy, Puppeteer version, Node version, and architecture.

9. Performance, reliability, and cost notes

Installing OS dependencies adds image size and build work; downloading Chrome adds a substantial transfer to fresh environments. Cache package-manager and browser-download layers where your build system supports it, while invalidating them when the base image, architecture, or Puppeteer version changes. Avoid installing packages on every test run.

Reliability depends on diagnosing the same binary and environment that actually run the screenshot test. A fix on a workstation does not fix a separate CI container. Keep the browser version, OS image, and package setup reproducible, and preserve diagnostic output when upgrades change the runtime requirements.

Self-hosted Puppeteer has no per-shot API charge, but the team maintains the browser download, OS libraries, container image, and execution capacity. Budget for image storage and CI compute according to your own environment; the cited Puppeteer guidance does not provide a screenshot-cost benchmark.

10. Or skip the browser setup

If you only need screenshots from URLs and do not need to run a custom Puppeteer test, ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request returns PNG, JPEG, WebP, or PDF. Its API documentation describes the available parameters.

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

ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. An MCP server gives AI agents such as Claude and Cursor tools to take screenshots, get page information, and capture PDFs.

The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan. Try it with a free ScreenshotNeo account.

11. FAQ

Should I install every package in Puppeteer’s Linux list?

Use the list as a reference for the relevant distribution. Prefer diagnosing the actual executable and installing the packages required by that host and browser version.

Does a successful ldd check prove Chrome will launch?

No. It checks shared-library resolution. Browser presence, permissions, sandbox policy, architecture, and runtime configuration can still prevent launch.

Can I use the OS-installed Chrome instead?

Yes, if your project deliberately configures Puppeteer to use it. Then diagnose that exact executable and confirm compatibility with your Puppeteer setup; do not use the downloaded-browser path for the checks.

Is --no-sandbox a suitable permanent CI fix?

Puppeteer strongly discourages it. Configure an appropriate sandbox for the host and follow the upstream guidance for host-specific restrictions.

Where should the fix live?

In the runtime environment that executes the test: typically the container image or CI worker setup. A package installed only on a separate build stage or developer machine will not satisfy that runtime.