# Playwright on VPS — Flags, Paths, Gotchas

**2026-08-15** — Playwright 1.62.0, Chromium 151

## Read-only root filesystem

The VPS root partition (`/root`, `/home`) is mounted read-only. Playwright defaults to `~/.cache/ms-playwright` for browser binaries — this fails with `EROFS` or `ENOENT`.

**Fix:** override the path at install and runtime:
```bash
PLAYWRIGHT_BROWSERS_PATH=/root/.hermes/playwright-browsers playwright install chromium
```
Every Playwright invocation must export this env var, or set it in the calling script.

## System library dependencies

Chromium headless needs these apt packages on a minimal Ubuntu install:
```
libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0
libxcomposite1 libxdamage1 libxrandr2 libgbm1 libpango-1.0-0
libcairo2 libasound2t64
```
(`libasound2` is the old name; Ubuntu 24.04+ uses `libasound2t64`.)

## Headless shell vs full chromium

Playwright 1.62+ downloads `chrome-headless-shell` by default, not full Chromium. It's smaller (115MB vs ~200MB) and works for scraping/screenshots. If you need the full browser (extensions, devtools), install `playwright install chromium` explicitly — but the headless shell is sufficient for lead scraping and site audits.

## Detection mitigation

- Set a realistic user agent: Windows Chrome, not headless default
- Add `page.wait_for_timeout(2000)` after navigation to let JS render
- Rotate delays (1.5–3s) between actions to avoid bot-pattern timing

## Writable paths on this VPS

| Path | Writable | Notes |
|---|---|---|
| `/root/.hermes/` | ✅ | rw mount — use for all persistent data |
| `/tmp/` | ✅ | rw — temp files, Playwright profiles |
| `/var/tmp/` | ✅ | rw — alternative temp |
| `/root/` (other) | ❌ | ro mount |
| `/home/` | ❌ | ro mount |
| `/root/.cache/` | ❌ | ro mount — override required |
