cimg/node:20.11-browsers
The image with “browsers” in the name ships no browser
If you pulled cimg/node:20.11-browsers expecting Chrome to be there and your job still says google-chrome: not found, you did nothing wrong. The tag is misleading. The -browsers layer adds the scaffolding a browser needs, not the browser itself.
Direct answer (verified 2026-06-16)
No, cimg/node:20.11-browsers does not contain Chrome or Firefox. It is built FROM cimg/node:20.11.1 and adds OpenJDK 11, the Selenium 3.141.59 standalone jar, an Xvfb virtual display, and the shared libraries Chrome and Firefox depend on, but no browser binary and no driver. You install the actual browser at job time with the circleci/browser-tools orb, or you skip the image entirely and let Playwright manage its own browsers. Source: the browsers Dockerfile.
Prove it in three commands
You do not have to take my word for it. Pull the image and look. Node is the version on the tin. The browser is absent. The only new binary the layer drops into /usr/local/bin is the Selenium jar.
That empty result from which google-chrome is the whole story. The image is named for what it is built to host, not what it contains.
What the -browsers layer actually adds
Read line by line from the published Dockerfile, here is everything the browsers variant stacks on top of the base Node image, and why each piece is there.
| In the layer | What | Why it is there |
|---|---|---|
| Base layer | FROM cimg/node:20.11.1 | Node 20.11.1 on CircleCI's Ubuntu-based convenience base. Everything below is stacked on top. |
| Java runtime | openjdk-11-jre | Installed only if Java is not already present. Selenium Server is a Java process, so it needs a JRE. |
| Selenium | selenium-server-standalone 3.141.59 → /usr/local/bin/selenium.jar | The Selenium grid jar, copied to a known path. This is the one binary the -browsers layer actually adds. |
| Virtual display | xvfb, entrypoint runs Xvfb :99 -screen 0 1280x1024x24 | A headless X server so a real browser window can render without a physical display. DISPLAY is set to :99. |
| Browser dependency libs | fonts-liberation, libasound2, libatk-bridge2.0-0, libgtk-3-dev, libxt6, libdbus-glib-1-2, … | The shared libraries Chrome and Firefox link against. Present so a later-installed browser can launch. Not a browser. |
| What is NOT here | google-chrome, chromedriver, firefox, geckodriver | No browser binary and no driver. You add those at job time with the circleci/browser-tools orb, or Playwright brings its own. |
The Selenium jar, the JRE, and Xvfb are all artifacts of a WebDriver-era testing model. If you are not running Selenium, almost none of this layer earns its place in your job.
Two ways to get a real browser into the job
There are two correct configs depending on what your tests run on. The first uses the image as CircleCI intends, with the orb installing Chrome. The second admits you probably do not need the -browsers image at all.
Path A — Selenium / WebDriver: install the browser with the orb
The -browsers tag and the browser-tools orb are a matched pair: the image carries the dependency libs, the orb drops in a pinned Chrome and ChromeDriver at runtime.
version: 2.1
orbs:
browser-tools: circleci/browser-tools@1
jobs:
e2e:
docker:
- image: cimg/node:20.11-browsers # amd64 only
steps:
- checkout
- browser-tools/install-browser-tools # <- installs the actual Chrome
- run: npm ci
- run: npm test # Selenium / WebDriver suite
workflows:
test:
jobs:
- e2ePath B — Playwright: skip the image, bring your own browsers
Playwright ships its own browser builds, pinned to the Playwright version in your package.json. It never looks for a system Chrome, so the Selenium jar and Xvfb in the browsers layer are dead weight. Run on the plain cimg/node:20.11 image and install browsers in one step.
version: 2.1
jobs:
e2e:
docker:
- image: cimg/node:20.11 # NOT -browsers; you don't need it
steps:
- checkout
- run: npm ci
- run: npx playwright install --with-deps # Playwright brings its own browsers
- run: npx playwright test
workflows:
test:
jobs:
- e2eIf you want zero install steps, you can also run directly on Microsoft's official Playwright image (mcr.microsoft.com/playwright), which already contains the browsers and OS dependencies matched to a Playwright release. The Playwright CI docs show the executor config for that route.
From red to green on the Playwright path
If you came here because of a failing job, this is the shortest route to a passing one without fighting the image.
Drop the -browsers suffix
Change the executor image to cimg/node:20.11 (or pin the full patch, cimg/node:20.11.1). You no longer need the Selenium scaffolding.
Install Playwright's browsers
Add a step that runs npx playwright install --with-deps. This pulls the exact browser builds your Playwright version expects, plus their OS dependencies.
Run the suite
npx playwright test now finds its browsers because Playwright put them there itself. No system Chrome, no orb, no DISPLAY juggling.
Cache the browser download (optional)
Browsers live under ~/.cache/ms-playwright. Cache that path keyed on your lockfile so the install step is near-instant on later runs.
If you are on Selenium and genuinely want the orb route, the same shape applies: keep the -browsers image and add browser-tools/install-browser-tools before your test step.
Where the tests themselves come from
Getting a browser into the job is the easy half. The harder half is writing and maintaining the tests that run in it. This is the part of the pipeline Assrt sits in. Assrt is an open-source tool that crawls your app, proposes the flows worth testing, and produces real Playwright tests, not a proprietary YAML format and not a closed cloud you have to keep paying. Because the output is standard Playwright, it runs in exactly the CircleCI job above with npx playwright test.
And it inherits the same browser story: since Assrt rides the Playwright engine, it leans on Playwright's own browser management, so you keep the lean cimg/node:20.11 executor and the single playwright install step rather than dragging the Selenium-era -browsers layer along. The tests live in your repo and your CI, with zero vendor lock-in. The source is open on GitHub and shipped as the @m13v/assrt package.
For the deeper version of the runner-versus-artifact decision, see the e2e testing framework guide, and for why CI environments drift away from local, see CI config drift.
When -browsers is still the right call
None of this means the tag is useless. If your suite is built on Selenium or raw WebDriver, you genuinely want the JRE, the Selenium jar, the Xvfb display, and the dependency libs already in place so the orb only has to drop in the browser. For those teams, cimg/node:20.11-browsers plus circleci/browser-tools is the canonical, well-trodden setup. The mistake is only assuming the word “browsers” means a browser is baked in, and reaching for this image on a Playwright project where a leaner base and one install step do the same job with less surface area. One caveat to plan around either way: the browsers variants are published for amd64 only, so an arm resource class will not match the image (tracked here).
Fighting your CI browser setup? Bring the failing job
We will look at whether you actually need the -browsers image, and how to get a real Playwright suite running green in your CircleCI pipeline.
Frequently asked questions
Does cimg/node:20.11-browsers come with Chrome preinstalled?
No. This is the single most common misunderstanding about the tag. The -browsers variant is built FROM cimg/node:20.11.1 and adds the things a browser needs to run, OpenJDK 11, a Selenium standalone jar, an Xvfb virtual display, and the shared libraries Chrome and Firefox link against, but it does not install any browser binary. If you run 'which google-chrome' inside the image, you get nothing. CircleCI's design is that you install the actual browser at job time using the circleci/browser-tools orb, which downloads a pinned Chrome and ChromeDriver (and optionally Firefox and geckodriver) into the running container.
What Node.js version does cimg/node:20.11-browsers actually use?
Node 20.11.1. The 20.11 tag is a rolling pointer to the latest 20.11.x patch release, and at the time the browsers Dockerfile was built that resolved to 20.11.1 (you can confirm with 'node --version' inside the container). If you need a frozen, reproducible version across rebuilds, pin the full patch tag, for example cimg/node:20.11.1-browsers, rather than the shorter 20.11-browsers.
Why does my CircleCI job say 'google-chrome: not found' or 'Could not find browser'?
Because the binary genuinely is not in the image. The job is doing exactly what you told it: the -browsers tag gives you Xvfb and Selenium scaffolding, but no Chrome. Two fixes work. If you are on Selenium or WebDriver, add the circleci/browser-tools orb and call its install-browser-tools step before your tests. If you are on Playwright, run 'npx playwright install --with-deps' (or use the official mcr.microsoft.com/playwright image), because Playwright ships and manages its own browser builds and does not look for a system Chrome at all.
Do I even need the -browsers image to run Playwright in CircleCI?
Usually not. Playwright bundles its own browser builds and is pinned to the Playwright version in your package.json, so the Selenium jar, OpenJDK, and Xvfb that the -browsers layer adds are dead weight for a pure Playwright suite. You have two cleaner options: run on the plain cimg/node:20.11 image and add a 'npx playwright install --with-deps' step, or run directly on Microsoft's official Playwright image (mcr.microsoft.com/playwright), which already contains the browsers and OS dependencies matched to a Playwright release. Both avoid the 'I pulled -browsers but Chrome still is not there' trap.
How is mcr.microsoft.com/playwright different from cimg/node:20.11-browsers?
They solve the same problem from opposite directions. cimg/node:20.11-browsers is a Node base plus the dependencies a system-installed browser needs, and it expects you to install that browser yourself (the orb's job). The Microsoft Playwright image already contains the browser binaries and all OS dependencies, pinned to a specific Playwright version, so you only run 'npm ci' and your tests. For a Playwright-only project the Microsoft image is the lower-friction choice; cimg/node:20.11-browsers makes more sense when your job mixes Node tooling with a Selenium or WebDriver suite.
Is the browsers variant available for arm64 (Apple Silicon, Graviton)?
No. The -browsers variants of cimg/node are published for amd64 (x86_64) only; arm64 support for the browsers tag is an open feature request on the cimg-node repository, not a shipped artifact. If your CircleCI executor uses an arm resource class, the -browsers image will not match. For arm Playwright runs, lean on Playwright's own 'npx playwright install --with-deps' on a plain arm Node image instead.
Keep reading
Playwright e2e testing
The runner most teams should start with, and how it manages its own browsers.
Headless Chrome test flakiness
Why headless browser runs go flaky in CI, and what actually fixes it.
CI config drift
When the test command that works locally quietly stops matching CI.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.