ScreenshotNeo

BlogHow-to

Puppeteer Screenshot on Alpine Linux: Install Chromium Dependencies

Install Alpine’s Chromium dependencies, configure Puppeteer’s executable path, and troubleshoot version, library, and container issues when capturing screenshots.

By the ScreenshotNeo team4 October 20268 min read

Short answer: Install Alpine’s Chromium package and its required libraries and fonts, point Puppeteer at the Chromium executable actually present in the image, and use a Puppeteer release compatible with that browser. Then build and test the exact image you will deploy. Alpine is a compatibility case: Puppeteer warns that Chrome does not support Alpine out of the box, and its standard Chrome system requirements list other Linux distributions.

This guide shows the Alpine-packaged Chromium route, a Docker setup, a screenshot script, and ways to diagnose common launch failures. Package names, executable paths, and browser compatibility depend on your Alpine release, architecture, and installed Chromium build.

1. Choose the browser installation approach

There are two practical choices:

  • Keep Alpine and install its Chromium package. This suits projects that must use an Alpine base image. You manage the package set, executable path, and compatibility checks for the exact image.
  • Use Puppeteer’s official Docker image. It bundles Chrome for Testing and its dependencies. Its documented sandbox invocation requires the SYS_ADMIN capability, and Puppeteer recommends an init process to manage child processes. It is an alternative container base, not an Alpine-based solution.

If Alpine is a firm requirement, use the package example below as a starting point. If it is not, compare the maintenance and security needs of your application before choosing a base image.

2. Install Chromium and Alpine dependencies

Puppeteer’s Alpine guidance gives this package list as an example:

chromium nss freetype harfbuzz ca-certificates ttf-freefont nodejs yarn

A minimal Dockerfile shape is:

FROM alpine
RUN apk add --no-cache \
  chromium nss freetype harfbuzz ca-certificates ttf-freefont nodejs yarn
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser

This is an illustrative starting point, not a certified recipe for every Alpine release. Check that the package names are available for your chosen Alpine version and architecture, and confirm the installed executable path. The example path is /usr/bin/chromium-browser; package layouts can differ.

Confirm the executable and shared libraries

Run these checks inside the built image, not only on your development machine:

command -v chromium-browser || command -v chromium
ls -l /usr/bin/chromium-browser /usr/bin/chromium 2>/dev/null || true

Use the path that exists when setting PUPPETEER_EXECUTABLE_PATH. If Chromium exists but will not start, inspect its shared-library dependencies. Replace the example binary path with the path found above:

ldd /usr/bin/chromium-browser | grep not

Any missing library reported by this command points to an incomplete or incompatible image dependency set. Resolve it for the selected Alpine and Chromium package; adding unrelated packages or changing screenshot options will not fix a missing shared library.

3. Match Puppeteer to Chromium

Puppeteer publishes a supported-browser mapping for the Chrome for Testing version associated with each Puppeteer release. The current documentation cited here maps Puppeteer v25.12.0 to Chrome for Testing 154.0.8037.57. That mapping does not certify compatibility with every Chromium version packaged by Alpine.

  1. Check the Chromium package version available for your Alpine release and architecture.
  2. Choose a Puppeteer release with a browser version compatible with that Chromium build, using Puppeteer’s supported-browser reference.
  3. Pin your Node package and Alpine base deliberately so a rebuild does not silently change one side of the pairing.
  4. Build and exercise the final image after any version change.

Puppeteer’s current system requirements state Node 22.12 or newer. Requirements and version mappings can change; consult the current official pages when selecting versions. Puppeteer also notes a timeout issue with Chromium on Alpine 3.20 and says downgrading to Alpine 3.19 fixes it. Treat that as a version-specific documented warning, not a rule for every Chromium and Alpine combination.

4. Launch Chromium and save a screenshot

Install Puppeteer as a project dependency using a release selected for the browser package in your image. When using Alpine’s separately installed Chromium, explicitly set the executable path so Puppeteer does not assume its downloaded Chrome for Testing binary is available.

const puppeteer = require('puppeteer');

async function main() {
  const executablePath = process.env.PUPPETEER_EXECUTABLE_PATH;
  if (!executablePath) {
    throw new Error('Set PUPPETEER_EXECUTABLE_PATH to the Chromium binary in this image');
  }

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

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

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

Save this as screenshot.js and run it in the container with Node. The finally block closes the browser even if navigation or capture fails. networkidle2 is a useful starting point, but sites with persistent network connections may never become idle; choose a different navigation condition or wait for a specific selector when appropriate. Puppeteer’s Page.screenshot() handles image capture only after Chromium has launched and the page has loaded.

Container sandboxing

Do not treat --no-sandbox as a routine Alpine dependency fix. Puppeteer’s troubleshooting guidance strongly discourages running without the browser sandbox and recommends sandboxes. If you consider disabling it in a container, account for the security tradeoff and use the appropriate sandbox configuration for your deployment. Missing libraries and an incompatible browser build need to be fixed directly.

5. Validate the final image

  1. Build the image for the same target architecture and Alpine release you will deploy.
  2. Check the Chromium path and inspect shared libraries inside that image.
  3. Run the screenshot script against a stable page and confirm the output file exists and is non-empty.
  4. Exercise the actual target site too: redirects, long loads, consent overlays, and dynamic content can behave differently from a simple test page.
  5. Repeat these checks after updating Alpine, Chromium, Node, or Puppeteer.

The exact package set and a validated Dockerfile cannot be specified without the Alpine version, architecture, Chromium package version, Puppeteer version, and container permissions. Treat the result as image-specific and keep the build check in your release workflow.

6. Troubleshoot launch and capture failures

Symptom Likely cause What to check or change
Browser executable not found Puppeteer is looking for its downloaded browser, or the configured path is wrong. Check command -v chromium-browser and command -v chromium in the image; set PUPPETEER_EXECUTABLE_PATH or executablePath to the path that exists.
Launch fails with a shared-library error A library required by this Chromium build is missing or incompatible. Run ldd against the actual Chromium binary and resolve missing dependencies for that Alpine package build.
Browser starts locally but fails in the container The local and deployed images differ in packages, architecture, permissions, or browser version. Run path, library, and screenshot checks inside the exact built image and target architecture.
Protocol or launch errors after an upgrade The Puppeteer release and Chromium build may not be compatible. Check the installed Chromium package version and Puppeteer’s supported-browser mapping; pin a compatible pair.
Navigation times out The site is slow, keeps connections open, or Alpine/Chromium has a version-specific issue. Check the target URL and logs, choose a suitable wait condition, and verify the Alpine/Chromium combination. Puppeteer documents a timeout issue for Chromium on Alpine 3.20 and a fix with Alpine 3.19.
Screenshot is blank or incomplete The page may not have rendered the needed content when capture ran, or navigation may have reached an error or blocked page. Wait for a page-specific selector or a suitable delay, inspect the final URL and page state, and confirm the output in the target image.
Fonts or text look different The image lacks fonts or has different font coverage from the development environment. Ensure the font packages needed by the page are present; the documented example includes ttf-freefont.
Browser exits unexpectedly or leaves processes behind Container process management or resource constraints may be involved. Close the browser in a finally block and use an init process as recommended for Puppeteer’s Docker setup; inspect container memory and logs.

7. Performance, reliability, and cost

For a self-hosted capture worker, Chromium startup, page load, and image rendering all consume time and memory. Reuse a browser process for multiple pages when your worker model allows it, but close pages and browsers predictably and isolate workloads that need separate browser state. Full-page captures and pages with heavy scripts or large images take longer and use more resources. Measure these behaviors in the target image and against your own pages; there is no single benchmark that applies to all sites and container sizes.

Reliability depends on keeping the OS package, Chromium build, and Puppeteer release compatible, then validating the exact image after changes. A pinned setup reduces surprise during rebuilds, while deliberate updates and capture checks help catch security and compatibility changes. Use timeouts and error handling so a slow or broken page does not hold a worker forever.

Self-hosting has infrastructure and maintenance costs: compute, memory, image builds, dependency updates, and operational work. The research sources provide no cost benchmark for this setup, so compare it with your actual volume and hosting costs.

Or skip the browser setup

If your goal is the screenshot rather than maintaining Chromium in Alpine, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. See the API documentation.

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

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.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://example.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
require('node:fs').writeFileSync('shot.webp', image);
  • Cookie banners are accepted and removed before capture; 60+ known consent platforms, newsletter popups, and chat widgets can be removed, with each step configurable.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed. Response headers report the page verdict and billing status.
  • An MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs.
  • The free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo’s free plan and capture 1,000 screenshots a month with no card.

Frequently asked questions

Can Puppeteer use Alpine’s system Chromium?

Yes, when the executable path is configured and the installed browser is compatible with your Puppeteer release. Validate both in the image you deploy.

Does Puppeteer’s installDeps option install Alpine dependencies?

No. Puppeteer documents that browser-install installDeps supports Chrome on Debian or Ubuntu only.

Is Alpine the easiest container base for Puppeteer?

It is a special compatibility case in Puppeteer’s documentation. If retaining Alpine is not a requirement, compare the maintenance of its Chromium package with Puppeteer’s official Docker image, which bundles Chrome and dependencies.