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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

To run Chrome Headless Shell in Docker, use a container with the browser’s operating-system dependencies, install or select the standalone chrome-headless-shell binary, and preserve Chrome’s sandbox. For Node.js projects using Puppeteer, the maintained ghcr.io/puppeteer/puppeteer image is the simplest documented starting point: run it with --init and --cap-add=SYS_ADMIN, then launch Puppeteer with headless: 'shell'.

First, distinguish Shell from Chrome’s other headless mode. Since Chrome 132, the regular Chrome binary’s --headless flag selects unified Headless; the former “old Headless” implementation is distributed separately as chrome-headless-shell. Shell can be lighter and more performant for suitable automation, while unified Headless more closely matches the full Chrome browser. The right choice depends on whether your workload prioritizes a leaner browser process or fuller browser fidelity.

What Chrome Headless Shell is—and when to use it

Chrome for Developers describes Headless Shell as a lightweight wrapper around Chromium’s //content module with substantially fewer dependencies. Chrome for Testing began distributing Shell binaries with Chrome 120; Chrome 132 is the key behavior change: old Headless stopped being an option in the regular Chrome binary and became the standalone Shell executable. See Chrome’s Headless documentation and Chrome for Testing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Choice How to select it Best fit Trade-off
Headless Shell Puppeteer: headless: 'shell'; standalone executable: chrome-headless-shell Automation tasks where Shell’s supported behavior is sufficient and a lighter implementation is useful Does not exactly match regular Chrome’s behavior or feature set
Unified Headless Regular Chrome with --headless, or Puppeteer with headless: true Tests requiring behavior closer to the full Chrome browser May be a less lean choice than Shell for tasks that do not need the extra fidelity

Chrome characterizes Shell as lighter and in some ways more performant, but actual speed depends on the workload; no universal performance result follows from that description. Choose unified Headless when end-to-end tests depend on browser features or behavior that Shell does not provide.

Choose a Docker installation approach

Use the Puppeteer image for Node.js and Puppeteer

The maintained Puppeteer image, ghcr.io/puppeteer/puppeteer, includes Chrome for Testing and required dependencies. Its documented run configuration uses --init to manage child processes and --cap-add=SYS_ADMIN for the image’s sandboxed browser configuration. It is a convenient Puppeteer starting point, not a Chrome-published Shell-only image. Puppeteer’s Docker guide reported version 25.12.0 on September 29, 2026; check the guide and available image tags when choosing a version because latest moves and version tags correspond to Puppeteer releases. See Puppeteer’s Docker guide.

For repeatable CI, pin a specific image version or digest rather than relying on latest. Keep the Puppeteer release and browser binary compatible: Puppeteer’s installer provides a Chrome for Testing build and Shell binary intended to work with that Puppeteer release. The documentation does not establish one universally correct tag for every project.

Install Shell in a custom image

For a custom Docker base or a non-Puppeteer stack, Chrome for Testing’s official installation command uses the @puppeteer/browsers utility:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
npx @puppeteer/browsers install chrome-headless-shell@stable

Use @stable to request the stable binary, or replace it with a specific version when pinning a reproducible build. The binary comes from Chrome for Testing’s release infrastructure. See Chrome for Testing and Puppeteer’s browser installation documentation.

A custom image must also provide the operating-system libraries required by that binary, a suitable user and sandbox configuration, and writable locations for browser profile, configuration, and cache data. Exact shared-library requirements depend on the base distribution and browser build, so do not copy a generic dependency list without checking it against your chosen image. No current Chrome-maintained Shell-only Dockerfile or image is established here. Chrome’s older Docker FAQ example based on node:8-slim is historical, not a current base-image recommendation.

Run Shell using the Puppeteer Docker image

The following pattern uses the documented image and runtime flags. Replace <pinned-version> with a real version tag that you have checked in Puppeteer’s Docker guide. The command assumes your script is available in the container as script.js; mount it read-only if it is on the host.

docker run --init --cap-add=SYS_ADMIN --rm 
  -v "$PWD/script.js:/app/script.js:ro" 
  -w /app 
  ghcr.io/puppeteer/puppeteer:<pinned-version> 
  node script.js

For example, this Puppeteer script explicitly selects Headless Shell and captures a page screenshot:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: 'shell' });
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com', { waitUntil: 'networkidle2' });
    await page.screenshot({ path: '/tmp/example.png', fullPage: true });
  } finally {
    await browser.close();
  }
})();

Ensure the output path is writable and copy or mount the result out of the container if it must persist. Puppeteer’s launch modes are distinct: headless: 'shell' selects the Shell binary, headless: true selects unified Headless, and headless: false requests visible Chrome. See Puppeteer’s Headless modes guide.

Run the Shell binary directly

If the binary is installed in a custom image and available on PATH, you can use its command-line capture options without Puppeteer. These examples follow Chrome’s documented CLI options; output directories must be writable by the container user.

Capture a screenshot

chrome-headless-shell 
  --no-first-run 
  --headless 
  --window-size=1440,1000 
  --screenshot=/tmp/page.png 
  https://example.com

Use --window-size to set the viewport dimensions for the capture. The screenshot flag writes an image file at the given path. Chrome’s CLI documentation is at Headless Chrome.

Print a PDF or inspect the rendered DOM

chrome-headless-shell --headless --print-to-pdf=/tmp/page.pdf 
  --no-pdf-header-footer https://example.com

chrome-headless-shell --headless --dump-dom https://example.com

--no-pdf-header-footer omits the printed headers and footers. --dump-dom serializes the DOM after the page has been parsed and scripts have run; it is not simply a dump of the original HTML response. For capture operations that should stop waiting after a defined interval, Chrome documents --timeout=<milliseconds>. Consult the CLI documentation for current option behavior and syntax.

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

Container settings that prevent common failures

Keep the sandbox and use an appropriate user

Do not add --no-sandbox as a routine startup fix. Chrome’s sandbox is a security boundary for browser content. Puppeteer recommends using a non-root user with a properly configured container; its documented image run instead grants SYS_ADMIN for its sandboxed browser configuration. Chrome’s FAQ says --no-sandbox is not needed when a user is properly set up in the container. Only consider disabling the sandbox when the content is absolutely trusted and you have consciously accepted the security trade-off. See Puppeteer troubleshooting and Chrome’s Headless FAQ and documentation.

Use an init process

Pass Docker’s --init flag, or use an init-capable entrypoint, so browser child processes are managed and reaped correctly. This matters for automation processes that launch and close browsers repeatedly; unmanaged children can outlive the main process or accumulate in a long-running container.

Provide writable profile and cache paths

Chrome writes profile, configuration, and cache data at startup. A read-only filesystem or unwritable home directory can prevent launch even when the executable and libraries are present. Puppeteer documents XDG_CONFIG_HOME, XDG_CACHE_HOME, and an explicit userDataDir as ways to place these files in writable locations. In restricted deployments, configure those paths and mount writable storage only where needed.

Do not install Xvfb for headless execution

Headless Shell does not create a visible display window. Chrome states that Xvfb is unnecessary for Headless execution, so adding a virtual X server is not a fix for missing browser libraries, sandbox problems, or unwritable profile paths.

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

Enable GPU acceleration only when the workload needs it

Puppeteer’s troubleshooting guidance notes that Shell needs --enable-gpu to enable GPU acceleration in Headless mode. Use it only if GPU compositing is useful for the workload and the Docker host exposes compatible GPU support; it is not a general requirement for screenshots or browser automation.

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
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting Chrome Headless Shell in Docker

Symptom Likely cause What to check or change
Browser exits immediately or reports a missing shared library The base image lacks a library required by the Shell build Install the dependencies for the selected binary and distribution. Do not assume a library list for another Linux base applies.
Sandbox initialization fails The container user or runtime capabilities do not match the sandbox setup Use the Puppeteer image’s documented --cap-add=SYS_ADMIN configuration, or correctly configure a suitable non-root user and sandbox for your custom image. Avoid defaulting to --no-sandbox.
Zombie or lingering browser processes No init process is reaping child processes Start with Docker’s --init or configure an init-capable entrypoint.
Browser cannot create a profile, cache, or config file Read-only container or unwritable home/config directories Set writable XDG_CONFIG_HOME, XDG_CACHE_HOME, and Puppeteer userDataDir paths; check volume ownership and permissions.
Test behavior differs from regular Chrome The test depends on a feature or behavior not available in Shell Run the test in unified Headless using regular Chrome and Puppeteer’s headless: true.
Expected GPU acceleration is absent Shell’s Headless GPU acceleration has not been enabled, or the host does not provide compatible GPU support Where supported and needed, add --enable-gpu and verify the container’s GPU access.
Build works locally but changes in CI An unpinned browser/image tag or mismatched Puppeteer and browser versions Pin an image version or digest and align Puppeteer with the browser binary downloaded for that release.

Choose between the ready image and a custom container

Consideration Puppeteer image Custom image
Setup effort Lower for Node.js projects already using Puppeteer; browser and required dependencies are included Higher; acquire the binary and account for distribution-specific libraries, user, sandbox, and storage
Version control Pin a Puppeteer image tag or digest; verify current tags Pin the Shell version through the installer and maintain the base image and dependencies
Runtime security Follow the image’s documented --init and SYS_ADMIN run configuration Configure user and sandbox for the chosen base; preserve writable paths without broadening permissions unnecessarily
Language and stack fit Best aligned with Node.js and Puppeteer More control for other stacks, at the cost of maintaining browser setup yourself

Or skip the browser setup

If the job is to capture a website rather than run browser automation inside your own container, ScreenshotNeo provides a screenshot API and MCP server for developers. A single GET request can return a PNG, JPEG, WebP, or PDF. Here is the cURL form using the supplied example target; read the ScreenshotNeo API documentation for the available parameters and setup:

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

ScreenshotNeo accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.

Create a free ScreenshotNeo account to try 1,000 screenshots a month without a card.

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.

Frequently Asked Questions

Does Chrome Headless Shell require Xvfb in Docker?

No. Chrome says Headless execution does not need Xvfb because it does not use a display window.

Can I use a specific Chrome for Testing Shell version instead of stable?

Yes. The @puppeteer/browsers installer accepts a version after chrome-headless-shell@; pin one for repeatable builds and keep it compatible with Puppeteer.

Does ScreenshotNeo require me to run a Chrome container?

No. It is a hosted screenshot API and MCP server; your request goes to its API rather than launching Chrome in your own Docker container.

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.

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