Skip to content
Independent guides for QA & test automationRSSEditorial policy
QA Vibes

Playwright "Executable doesn't exist": Why the Browser Revision in the Path Changed, and How to Fix It

"browserType.launch: Executable doesn't exist" reproduced by upgrading Playwright from 1.63.0 to 1.64.0 with one browser cache: the path asks for chromium_headless_shell-1248 and the cache holds 1243. Where that revision comes from, what npx playwright install removes, why installing browsers before npm ci gets the wrong revision, and which CI and Docker setups avoid it.

QA Vibes EditorialPublished 7 minTested with Playwright 1.63.0, Playwright 1.64.0, Node.js 20.20.2, Windows 11Revision history ↓

Key takeaways

  • Each Playwright version needs one specific browser build, named by the revision in the path. Upgrading from 1.63.0 to 1.64.0 changed it from 1243 to 1248.
  • The revision comes from browsers.json in the installed playwright-core package, so the error follows your lockfile, not the version you think you have.
  • Run npx playwright install from the project, after npm ci. Before npm ci, npx used the latest Playwright and planned to install revision 1248 for a project on 1.63.0.
  • npx playwright install removed the old builds as unused, but kept them while a second project on the old version used the same cache.
  • Don't restore a browser cache from another Playwright version. Playwright's docs advise against caching browsers in CI at all; if you do, key the cache on the Playwright version.
Contents (10 sections)

Introduction

"Error: browserType.launch: Executable doesn't exist at …\ms-playwright\chromium_headless_shell-1248\chrome-headless-shell-win64\chrome-headless-shell.exe" means Playwright went to start its browser and the file wasn't there. Your code is fine. The browser build that this version of Playwright expects was never downloaded to the place it looked.

The fix is usually one command, but the error keeps coming back in CI, Docker and serverless deploys, because the reason is easy to miss: each Playwright version needs its own browser build, and the number in the path says which. This page reproduces the error on 13 October 2026 by upgrading Playwright from 1.63.0 to 1.64.0 with one browser cache, on Windows 11 with Node.js 20.20.2, and checks each fix.

The repro

We used an empty browser cache folder of our own, set with PLAYWRIGHT_BROWSERS_PATH, so the run didn't touch the machine's normal cache. Paths below are shortened to …\pwcache.

The project is one config and one test. playwright.config.ts:

import { defineConfig } from "@playwright/test";
 
export default defineConfig({
  testDir: "./tests",
  reporter: "list",
  projects: [{ name: "chromium", use: { browserName: "chromium" } }],
});

tests/smoke.spec.ts:

import { test, expect } from "@playwright/test";
 
test("opens a page", async ({ page }) => {
  await page.setContent("<h1>Hello</h1>");
  await expect(page.getByRole("heading", { name: "Hello" })).toBeVisible();
});

With @playwright/test 1.63.0, npx playwright install chromium downloaded two Chromium builds into the cache, and the test passed:

chromium-1243
chromium_headless_shell-1243
ffmpeg-1011
winldd-1007

Then we upgraded with npm i -D @playwright/[email protected], and ran the test again without installing anything:

Running 1 test using 1 worker
 
  x  1 [chromium] › tests\smoke.spec.ts:3:5 › opens a page (7ms)
 
  1) [chromium] › tests\smoke.spec.ts:3:5 › opens a page ───────────────────────────────────────────
 
    Error: browserType.launch: Executable doesn't exist at …\pwcache\chromium_headless_shell-1248\chrome-headless-shell-win64\chrome-headless-shell.exe
    ╔════════════════════════════════════════════════════════════╗
    ║ Looks like Playwright was just installed or updated.       ║
    ║ Please run the following command to download new browsers: ║
    ║                                                            ║
    ║     npx playwright install                                 ║
    ║                                                            ║
    ║ <3 Playwright Team                                         ║
    ╚════════════════════════════════════════════════════════════╝

The test failed in 7 ms, before any browser started. The cache still held build 1243, and Playwright 1.64.0 asked for 1248.

Where the number in the path comes from

The folder name is the browser name and a revision: chromium_headless_shell-1248. Each playwright-core release lists the revisions it was built against in node_modules/playwright-core/browsers.json. In 1.64.0 the Chromium entries were:

[
  { "name": "chromium", "revision": "1248", "installByDefault": true, "browserVersion": "156.0.8078.4", "title": "Chrome for Testing" },
  { "name": "chromium-headless-shell", "revision": "1248", "installByDefault": true, "browserVersion": "156.0.8078.4", "title": "Chrome Headless Shell" }
]

npx playwright install --dry-run chromium prints the same thing without downloading, so you can check what a project needs:

Chrome for Testing 156.0.8078.4 (playwright chromium v1248)
Chrome Headless Shell 156.0.8078.4 (playwright chromium-headless-shell v1248)

For the 1.63.0 project it said Chrome for Testing 153.0.8010.12 (playwright chromium v1243). So the revision follows the playwright-core that is actually installed in node_modules, which is whatever your lockfile resolved, not the range in package.json. Our project said "^1.63.0" before the upgrade, a range that 1.64.0, the latest release that day, also satisfies; without the lockfile, a fresh install could resolve to it and ask for 1248.

Two more things in the path are worth reading:

  • Which build. Our headless run looked for chromium_headless_shell-…; the full browser is in chromium-…. A plain npx playwright install chromium downloaded both.
  • Which folder. The start of the path is the cache Playwright searched: by default %USERPROFILE%\AppData\Local\ms-playwright on Windows, ~/Library/Caches/ms-playwright on macOS and ~/.cache/ms-playwright on Linux, or PLAYWRIGHT_BROWSERS_PATH if it's set (Playwright's browsers documentation). The default is inside the home folder, so browsers installed as one user are not where Playwright looks when the tests run as another.

The fix: install from the project

In the 1.64.0 project, npx playwright install chromium downloaded build 1248 (197.5 MiB for Chrome for Testing, 118.1 MiB for the headless shell) and removed the old ones:

Removing unused browser at …\pwcache\chromium-1243
Removing unused browser at …\pwcache\chromium_headless_shell-1243
Removing unused browser at …\pwcache\ffmpeg-1011
Downloading Chrome for Testing 156.0.8078.4 (playwright chromium v1248) from https://cdn.playwright.dev/builds/cft/156.0.8078.4/win64/chrome-win64.zip
…

The test then passed. The removal is Playwright's cleanup: it records which projects use the cache, in a .links folder inside it, and deletes builds no project needs. To check that, we added a second project on 1.63.0 that used the same cache. Before its own install it failed the same way, now looking for chromium_headless_shell-1243, which the first project's install had removed. After npx playwright install chromium in the second project, the cache held both revisions, .links had two entries, and a later install in the first project removed nothing. Both projects' tests passed. So two projects on different Playwright versions can share a cache, as long as each has run its own install.

Install before npm ci, and you get the wrong browser

npx playwright install uses the Playwright in the project's node_modules. If there isn't one yet, npx fetches the latest Playwright and uses that. In the 1.63.0 project, with node_modules deleted:

== before npm ci
Version 1.64.0
Chrome for Testing 156.0.8078.4 (playwright chromium v1248)
Chrome Headless Shell 156.0.8078.4 (playwright chromium-headless-shell v1248)
== after npm ci
Version 1.63.0
Chrome for Testing 153.0.8010.12 (playwright chromium v1243)
Chrome Headless Shell 153.0.8010.12 (playwright chromium-headless-shell v1243)

Before npm ci, npx playwright --version printed 1.64.0, and the install would have fetched build 1248, which this project can't use. After npm ci it was the project's 1.63.0 and build 1243. A CI job or Dockerfile that installs browsers in a step before the dependencies, or in a different folder, ends up with the latest Playwright's browsers and fails with this error as soon as the latest version is newer than yours.

This site's own CI runs npm ci first, then npx playwright install --with-deps chromium in the project folder, on every run, without caching browsers.

CI and Docker

Don't restore a browser cache from another Playwright version. A cache restored by a CI job is the same situation as our upgrade: the folder holds the old revision, and the new Playwright asks for the new one. Playwright's CI documentation says caching browser binaries is not recommended, because restoring the cache takes about as long as downloading again, and that if you cache them anyway the key should include the Playwright version. The version that decides the revision is the installed one, which this prints:

node -p "require('playwright-core/package.json').version"

Install where the tests run. If the install runs in one environment and the launch in another (a separate build step, another user, another container), the path in the error is in a folder the install never wrote to. Install in the same environment as the run, or point PLAYWRIGHT_BROWSERS_PATH at a folder both use. Playwright's browsers documentation also describes PLAYWRIGHT_BROWSERS_PATH=0, which installs the browsers inside node_modules; we didn't run that variant here.

Docker: match the image to the project. Microsoft's Playwright images, such as mcr.microsoft.com/playwright:v1.64.0-noble, contain the browsers for one Playwright version. Playwright's Docker documentation says that if the image's version doesn't match the project's, Playwright can't find the browser executables. We set out to show that with the 1.64.0 project in the 1.63.0 and 1.64.0 images, but couldn't: Docker on our test machine failed to pull the images (its disk was full), so that part is documented, not measured here. Pin the image tag to the exact version in your lockfile, and update both together.

How to prevent it

  • Install browsers after the dependencies, from the project. npm ci, then npx playwright install (add --with-deps on Linux CI for the system libraries).
  • Pin Playwright exactly, or commit the lockfile. Then the revision only changes when you change it.
  • Treat a Playwright upgrade as a browser upgrade. Every version bump needs a new install, locally, in CI and in your Docker base image.
  • When you see the error, read the path. The revision tells you which Playwright wanted it, the build name tells you which browser, and the folder tells you which cache was searched. Compare with npx playwright install --dry-run in the same environment.

Exercise

In a project on Playwright 1.64.0, run npx playwright install --dry-run chromium and note the revision. Then npm i -D @playwright/[email protected] and run it again. Predict what npx playwright install chromium will remove from your cache, and what a second project still on 1.64.0 would need afterwards, then check.

If the browser starts and closes again before your test is done, the error is a different one: see Target page, context or browser has been closed. If the launch works but a step runs out of time, see timeout errors. Our CI/CD guide shows a full pipeline.

Conclusion

"Executable doesn't exist" means the browser build this Playwright version needs isn't in the cache it searched. The revision in the path comes from the installed playwright-core, and it changes with every Playwright version: 1243 for 1.63.0, 1248 for 1.64.0. Run npx playwright install from the project after npm ci, don't reuse a browser cache across versions, keep Docker images on the same version as the lockfile, and read the path in the error: it says which version, which browser and which folder.

Sources and further reading

Tools mentioned

PlaywrightUI AutomationOpen source

Links go to each tool’s official site. How we choose and link tools

Revision history

First published.

Spotted a mistake? Report it — corrections land here.

Written and reviewed by

QA Vibes Editorial

Articles are written and reviewed by practicing QA and automation engineers. Every article lists its sources and shows when it was last updated.