# ZimaOS Playwright v2 Browser Recipe (2026-05-09)

Session: Upgraded from Chromium `--dump-dom` CLI (v1) to Playwright-based real browser automation (v2) inside a Debian Docker container on ZimaOS.

## What changed from v1 → v2

| Feature | v1 (CLI `--dump-dom`) | v2 (Playwright) |
|---------|----------------------|-----------------|
| Interaction | None | Real mouse click, type, scroll, evaluate JS |
| Engine | Chromium subprocess | Playwright + async browser pool |
| Anti-detection | Basic flags | Full stealth: `navigator.webdriver` removed, fake plugins, locale de-DE, timezone Europe/Vienna |
| API framework | `http.server` (blocking) | `aiohttp` (async) |
| Endpoints | `/health`, `/visit`, `/screenshot` | + `/navigate`, `/click`, `/type`, `/scroll`, `/evaluate` |

## Verified working commands for ZimaOS

**1. Start Debian container**
```bash
sudo docker run -d --name kiwi-browser debian:bookworm-slim sleep 3600
```

**2. Install base packages**
```bash
sudo docker exec kiwi-browser apt-get update -qq
sudo docker exec kiwi-browser sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends chromium python3 python3-pip curl ca-certificates fonts-liberation && rm -rf /var/lib/apt/lists/*'
```

**3. Install Playwright + aiohttp**
> Pitfall: Debian 12 marks pip as "externally managed". You MUST use `--break-system-packages`.
```bash
sudo docker exec kiwi-browser pip3 install --break-system-packages playwright aiohttp
sudo docker exec kiwi-browser playwright install chromium
```

**4. Copy v2 server script into container**
```bash
sudo docker cp kiwi-browser-server-v2.py kiwi-browser:/app/server-v2.py
```

**5. Commit and start**
```bash
sudo docker stop kiwi-browser
sudo docker commit kiwi-browser kiwi-browser:v2
sudo docker rm kiwi-browser
sudo docker run -d \
  --name kiwi-browser \
  --restart unless-stopped \
  -p 0.0.0.0:30000:3000 \
  kiwi-browser:v2 \
  bash -c 'cd /app && python3 server-v2.py > /app/server-v2.log 2>&1'
```

**Verify**
```bash
curl -s http://127.0.0.1:30000/health
# → {"status": "ok", "version": "v2-playwright"}
```

## Key v2 API endpoints

- `POST /click` — click by CSS selector or (x,y) coordinates
- `POST /type` — type into input, optional submit (Enter)
- `POST /scroll` — direction: down/up/bottom/top, or scroll-to selector
- `POST /evaluate` — execute arbitrary JS in page context

## Anti-detection config baked into v2 server (from `BrowserPool.start`)

```python
args=[
    "--no-sandbox",
    "--disable-gpu",
    "--disable-dev-shm-usage",
    "--disable-background-networking",
    "--disable-background-timer-throttling",
    "--disable-backgrounding-occluded-windows",
    "--disable-renderer-backgrounding",
    "--disable-features=IsolateOrigins,site-per-process",
    "--disable-blink-features=AutomationControlled",
]
```

Plus init script:
```javascript
Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
Object.defineProperty(navigator, 'plugins', {get: () => [1,2,3,4,5]});
window.chrome = { runtime: {} };
Object.defineProperty(navigator, 'languages', {get: () => ['de-DE', 'de', 'en-US', 'en']});
```

## Pitfalls discovered

- `pip3 install playwright` without `--break-system-packages` fails on Debian Bookworm with PEP 668 externally-managed error.
- Container startup with `nohup &` in `docker exec` does not work — must commit image and use `docker run -d`.
- Each endpoint creates a fresh browser context (`new_page`) — good for isolation, but cookies/session don't persist across calls. For session persistence, keep a context open across requests (not yet implemented).
- DuckDuckGo returns "Unexpected error" after automated form submission — some sites detect automation even with Playwright stealth.

## Image sizes

- Debian Bookworm Slim base: ~30 MB
- With Chromium + Python + Playwright: ~600 MB
- Playwright Chromium binary cache (`/root/.cache/ms-playwright/`): ~180 MB

## Next steps (not yet built)

- Cookie persistence via Docker volume mount on `/root/.config/chromium`
- Proxy rotation support
- Session persistence across API calls (re-use context)
- YouTube Studio upload automation step-by-step recipe
