A fresh checkout last week ran npx playwright install for the first time in months and surfaced a du -sh ~/Library/Caches/ms-playwright of 11.3 GB across seven Chromium builds, five Firefox, and four WebKit, all on a single laptop. None of it lived inside any node_modules. None of it showed up in macOS Storage as anything but the gray System Data bar. The pain pattern is the one a developer described at brtkwr.com after freeing 200 GB on a full disk: "After the initial Docker/cache cleanup freed 150GB, going back and asking 'what else?' found another 75GB." Playwright's browser cache is one of those what else wins.
Where is the Playwright cache location on Mac?
Playwright's browser cache on macOS lives at ~/Library/Caches/ms-playwright by default. Inside that folder you get one subdirectory per browser-version pairing that any Playwright release has ever pinned on this machine, like chromium-1124, firefox-1466, webkit-2090, plus ffmpeg-1010 for video recording. Each subfolder is a fully unpacked browser application bundle.
Two things to keep clear. The cache is shared across all projects on the user account by default, every Node project depending on @playwright/test reads from the same path. And the cache is additive. Playwright never garbage-collects an old browser version when a newer one arrives, so four @playwright/test bumps this quarter means four full Chromium builds in the cache.
The one command that tells you the truth is this.
# Honest size of the entire Playwright browser cache
du -sh ~/Library/Caches/ms-playwright
# Per-version breakdown, biggest first
du -sh ~/Library/Caches/ms-playwright/*/ 2>/dev/null \
| sort -hr \
| head -20
That second number is the one to trust. Finder's Get Info on ~/Library/Caches bundles in Yarn, Homebrew, pip, huggingface, and a dozen other tools none of which Playwright owns.
Why does the Playwright cache get so big?
Three reasons stack up on a developer Mac.
First, Playwright ships three full browsers by default. Chromium, Firefox, and WebKit each unpack to roughly 300 to 450 MB. The FFmpeg helper adds another 50 to 80 MB. A single npx playwright install lands close to 1.2 GB before the project runs a single test.
Second, every minor @playwright/test release pins new browser revision numbers. The cache keeps the old subfolders untouched. After eight months of dependabot bumps you have chromium-1098, chromium-1112, chromium-1124, and chromium-1131 sitting next to each other, each 400 MB, none of them read anymore.
Third, monorepos with multiple Playwright versions multiply the count. If your e2e app pins @playwright/test@1.41 and a tooling package pins 1.46, both versions install their own browser triples into ~/Library/Caches/ms-playwright, because the cache key is the binary version, not the wrapper version.
The table below is what the cache footprint looks like next to the other browser-and-cache offenders on a Mac with a year of mixed JS work.
| Cache | Default Mac location | Audit command | Typical 12-month size |
|---|---|---|---|
| Playwright browsers | ~/Library/Caches/ms-playwright |
du -sh ~/Library/Caches/ms-playwright |
6 to 12 GB |
| Puppeteer Chrome | ~/.cache/puppeteer |
du -sh ~/.cache/puppeteer |
1 to 3 GB |
| Cypress binary | ~/Library/Caches/Cypress |
du -sh ~/Library/Caches/Cypress |
2 to 5 GB |
| npm cache | ~/.npm/_cacache |
du -sh ~/.npm/_cacache |
3 to 8 GB |
| pnpm store | ~/Library/pnpm/store/v3 |
du -sh "$(pnpm store path)" |
8 to 20 GB |
| Yarn (classic) cache | ~/Library/Caches/Yarn |
du -sh ~/Library/Caches/Yarn |
2 to 6 GB |
Add those rows and an e2e-heavy JS Mac has 20 to 50 GB of test-tooling caches before the first node_modules folder. The Playwright cache is usually the second largest, and the one developers forget exists, because the install command finishes once and never speaks again.
How do I audit the Playwright cache safely?
Four steps. Honour PLAYWRIGHT_BROWSERS_PATH if set, measure the directory, list per-version subfolders, then ask Playwright what the current project actually needs.
# 1. Honour any PLAYWRIGHT_BROWSERS_PATH override
echo "${PLAYWRIGHT_BROWSERS_PATH:-$HOME/Library/Caches/ms-playwright}"
# 2. Honest size of the cache directory itself
du -sh "${PLAYWRIGHT_BROWSERS_PATH:-$HOME/Library/Caches/ms-playwright}"
# 3. Top 20 heaviest browser builds, biggest first
du -sh "${PLAYWRIGHT_BROWSERS_PATH:-$HOME/Library/Caches/ms-playwright}"/*/ 2>/dev/null \
| sort -hr \
| head -20
# 4. Which versions does the current project still pin?
npx playwright install --dry-run
The fourth command decides the cleanup. --dry-run prints the browser revisions the current @playwright/test would install if asked. Anything in the cache that does not appear in that list is stale. Hold that list before you delete anything, it is the shortest path from "the cache is 11 GB" to "this is the 1.2 GB I actually need."
For the wider audit beyond Playwright, see find-all-node-modules-mac and docker-system-prune-explained.
How do I run npx playwright uninstall correctly?
Playwright ships two uninstall modes and they are not interchangeable.
npx playwright uninstall is surgical. Run it from a project root and it deletes only the browser revisions pinned by the @playwright/test version in that project. Anything tied to a different version on the machine survives.
npx playwright uninstall --all is the wider sweep. It clears every browser, every version, every helper in ~/Library/Caches/ms-playwright. The next npx playwright install in any project rebuilds whatever that project pins.
# Project-scoped: drop only the browsers tied to this @playwright/test
cd ~/code/my-app
npx playwright uninstall
# Machine-scoped: clear the entire ms-playwright cache
npx playwright uninstall --all
# Verify
du -sh ~/Library/Caches/ms-playwright
For the absolute floor of safety, do not call --all directly. The uninstall commands hard-delete, the same way rm -rf does, and once the bytes are gone they are gone. The Trash-first move in the next section costs you nothing and buys a seven-day window to put a browser back if a forgotten CI mirror insists on a specific Chromium revision.
How do I move the ms-playwright folder to Trash instead?
For a developer Mac, the safer mirror of npx playwright uninstall --all is a timestamped move into ~/.Trash. That keeps everything reversible from Finder, gives macOS its standard seven-day cleanup window, and lets you put a version back with a single drag if the cleanup turns out to have been too aggressive. This is the same Move to Trash floor the CleanMyDev safety model applies to every dev cache.
# 1. Confirm the cache path one more time
CACHE="${PLAYWRIGHT_BROWSERS_PATH:-$HOME/Library/Caches/ms-playwright}"
du -sh "$CACHE"
# 2. Timestamped move to Trash, not rm -rf
STAMP=$(date +%Y%m%d-%H%M%S)
mv "$CACHE" "$HOME/.Trash/ms-playwright-$STAMP"
# 3. Re-pin only what the current project actually needs
cd ~/code/my-app
npx playwright install --with-deps
mv is an APFS metadata operation on the boot volume, so even an 11 GB cache moves in under a second. The timestamp matters: two cleanups in the same week would collide on ms-playwright as a Trash name otherwise. --with-deps is a no-op for system libraries on macOS, safe to keep in muscle memory even when you switch between Linux CI and a Mac laptop.
Can I move the Playwright cache off the boot disk?
Yes, and on a 512 GB MacBook running multiple Playwright projects this is worth doing once and forgetting. Playwright reads PLAYWRIGHT_BROWSERS_PATH on every install.
Set PLAYWRIGHT_BROWSERS_PATH=0 and the next npx playwright install writes browsers into node_modules/playwright-core/.local-browsers for that project alone. The shared cache stops accumulating, the tradeoff is every project pays its own 1.2 GB. Or relocate the shared cache to an external SSD: Playwright treats /Volumes/External/ms-playwright exactly like the default.
# Option A: per-project browsers, no shared cache
echo 'export PLAYWRIGHT_BROWSERS_PATH=0' >> ~/.zshrc
# Option B: shared cache on an external SSD
echo 'export PLAYWRIGHT_BROWSERS_PATH=/Volumes/External/ms-playwright' >> ~/.zshrc
# Confirm in a new shell
echo "$PLAYWRIGHT_BROWSERS_PATH"
Pick the first if your e2e tests live inside one or two projects and you want hermetic node_modules. Pick the second if you have a half-dozen Playwright projects and want a single shared cache off the boot disk.
What about trace, video, and report folders?
The browser cache is the largest pile, but it is not the only one Playwright writes. A test run also drops trace zips, video recordings, screenshots, and HTML reports inside each project at test-results/ and playwright-report/. A debug session that captured an hour of video at full resolution can leave a single test-results/ folder at 4 to 8 GB.
find ~/code -type d \( -name 'test-results' -o -name 'playwright-report' \) -prune \
-exec du -sh {} \; 2>/dev/null \
| sort -hr | head -20
Move those to Trash the same way you move build artifacts. The find ... -prune flag is the same trick covered for node_modules in find-all-node-modules-mac.
When should I not clean the Playwright cache?
If a CI mirror on this machine pins a specific browser revision and your test infra cannot tolerate even a five-minute redownload, schedule the cleanup outside CI hours. If you are mid-investigation on a Playwright bug and have a trace.zip open in the trace viewer, close the viewer first, the viewer reads browser binaries from the cache during replay. If you are on a metered or offline network, hold off until you can pay the 1.2 GB rebuild cost.
Cleanup playbook in order
- Move
~/Library/Caches/ms-playwrightto Trash with a timestamp. Reclaims 6 to 12 GB. - Re-pin the current project's browsers with
npx playwright install --with-deps. - Set
PLAYWRIGHT_BROWSERS_PATHto0or an external SSD path. - Sweep
test-results/andplaywright-report/folders in each project. - Re-audit monthly. The same pattern repeats for npm-cache-location-mac and the parallel test runner caches.
Why use CleanMyDev for this instead?
The terminal flow above is honest, reversible, and free. It also asks you to remember PLAYWRIGHT_BROWSERS_PATH, the difference between project-scoped and machine-scoped uninstall, and the trace-viewer caveat every time.
CleanMyDev audits ~/Library/Caches/ms-playwright, lists every cached browser version with its last-used date, and shows which versions are still pinned by any @playwright/test install. Tick the rows you want, hit Move to Trash, receipts stay in Finder for seven days. The same view stacks alongside Puppeteer, Cypress, npm, pnpm, Bun, Yarn, and Docker caches. $9.99 lifetime, no subscription, Trash by default. See the pricing on the homepage.