skip to content

In Playwright, what does setting PLAYWRIGHT_BROWSERS_PATH change about where engine builds live?

level: middleimportance: should knowfreq 44%

answer

  1. Overrides the default cache location
  2. Read at install time and run time
  3. Absolute path or the value zero
  4. Zero means inside node_modules
  5. Asymmetric setting causes a missing executable

basics

~20 s

It moves the directory Playwright installs engine builds into and reads them from. An absolute path selects that directory; the value 0 puts the builds inside the installed package itself, giving the project its own private copy.

solid answer

~40 s

By default engines go into an OS-specific `ms-playwright` cache folder shared by every project on the machine. `PLAYWRIGHT_BROWSERS_PATH` overrides it, and it is read by **both** the installer and the runtime — that symmetry is the whole point. Set it to an absolute path to choose the directory; set it to `0` to install into a `.local-browsers` folder inside the `playwright-core` package under `node_modules`, so the checkout carries its own engines and deleting `node_modules` deletes them too. The classic failure is setting it for only one half: install with it and run without it and the runtime searches the default cache, finds nothing, and throws `Executable doesn't exist at ...` even though the build is on disk. It changes location only — never which engines or which revisions.

code

bash · 5 lines
bash
export PLAYWRIGHT_BROWSERS_PATH=$HOME/pw-browsers
npx playwright install chromium
npx playwright test

PLAYWRIGHT_BROWSERS_PATH=0 npx playwright install chromium

go deeper

for a junior

Know that Playwright keeps engines in a cache folder called ms-playwright and that this variable points that folder somewhere else. Set it consistently for both the install and the run.

for a middle

Explain the three settings — unset, an absolute path, and 0 for a package-local copy — and why the variable being read by both installer and runtime is what makes asymmetric settings fail.

for a senior

Diagnose from the symptom: a missing-executable error on a machine where the build clearly exists is a path mismatch, and --list tells you which directory actually holds it.

for a principal

Weigh a shared cache against per-project isolation for the estate: sharing saves download time and disk, isolation guarantees a project's engines cannot be moved by another project's upgrade.

## The default: one shared cache per user With nothing set, Playwright installs engine builds into an OS-specific folder named `ms-playwright` — `~/.cache/ms-playwright` on Linux, `~/Library/Caches/ms-playwright` on macOS, `%USERPROFILE%\AppData\Local\ms-playwright` on Windows. Every project on the machine shares it, so five checkouts on the same Playwright version download one copy of each engine between them. `PLAYWRIGHT_BROWSERS_PATH` overrides that location. It is read by both the installer and the runtime, which is the single most important thing about it. ## The three settings it can take | Value | Where builds live | Typical reason | |---|---|---| | unset | the OS cache folder | the default; shared across projects | | an absolute path | that directory | a chosen disk, an image layer, a shared volume | | `0` | inside the installed package itself | a self-contained per-project copy | - An **absolute path** is what you want when the default location is the wrong disk, is not writable, or should be somewhere you control the lifetime of. - **`0`** puts the builds in a `.local-browsers` directory inside the `playwright-core` package under `node_modules`, so the checkout of the hotel-booking suite carries its own engines and nothing is shared with other projects. Deleting `node_modules` deletes the engines with it. - A relative path is resolved to an absolute one, because the value must mean the same directory at install time and at run time. ## The failure mode: set in one place only Because the same variable answers "where do I put these?" and "where do I find these?", setting it asymmetrically is the classic mistake: 1. Install with the variable set, run without it — the runtime looks in the default cache, finds nothing, and throws `Executable doesn't exist at ...` even though the build is on the disk. 2. Install without it, run with it set — the same error, with the roles reversed. 3. Change the path after installing — the old location keeps the only copy, and nothing points at it any more. Export it in a place both halves inherit, or pass it on both commands. `npx playwright install --list` prints the builds across all Playwright installations, which is the fastest way to see whether the problem is a missing download or a path mismatch. ## What it does not change - It does not change **which** engines are downloaded or their pinned revisions; those follow the Playwright package version. - It does not skip the download. The variable that suppresses the automatic fetch performed while packages are being installed is `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD`, used when the binaries are managed separately. - It does not change the **layout** inside the directory: you still get revision-stamped folders such as `chromium-1244`, so several Playwright versions coexist in one location without colliding. ## Why the choice matters A shared default cache is the right thing on a developer machine: it is written once and reused by every project, and Playwright's own housekeeping removes builds no installation still references. A dedicated path is the right thing when you want the engines on a known volume or under your own lifecycle control. `0` is the right thing when isolation beats sharing — when the booking suite must be certain that the engine it runs came from its own dependency tree and cannot be disturbed by a sibling project's upgrade. The cost of `0` is duplication: every checkout pays the full download and the full disk footprint, and removing a node_modules directory means downloading again.

  • What does PLAYWRIGHT_BROWSERS_PATH=0 buy you over a shared cache?
    Isolation. The engines live in a `.local-browsers` directory inside the installed `playwright-core` package, so the project's engines come from its own dependency tree and no sibling project can disturb them. The cost is duplication: every checkout pays the full download and disk footprint, and clearing node_modules means downloading again.
  • Which variable stops the engines being fetched at all, and when would you use it?
    `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD`, set before the packages are installed. It suppresses the automatic download performed as part of package installation, and it exists for setups where the binaries are managed separately and provided by other means. It is about skipping the fetch, not about relocating it.

saying these in an interview costs you the question

  • Thinks it selects which browsers get installed
  • Sets it only for the test run, not the install
  • Believes zero disables downloading entirely
  • Assumes a relative path is kept relative
  • Expects it to change the pinned engine revisions