# zendriver-mcp
**Undetectable browser automation for LLM agents, spoken over MCP.**
`zendriver-mcp` is an [MCP](https://modelcontextprotocol.io) server that gives
your coding agent (Claude, Cursor, Gemini, Copilot) a real Chrome browser it
can actually use on the real web - behind Cloudflare, behind login walls, on
pages that detect and block WebDriver.
It's built on [Zendriver](https://github.com/cdpdriver/zendriver), which speaks
the Chrome DevTools Protocol directly instead of going through WebDriver. That
means no `navigator.webdriver` flag, no headless telltales, and a fingerprint
that looks like an ordinary Chrome install.
On top of that foundation, `zendriver-mcp` layers everything an agent needs
to get work done: a token-efficient DOM walker, an accessibility tree with
stable uids, performance traces, Lighthouse audits, heap snapshots, human-like
input, device emulation, cookie round-tripping, and more - **96 tools across
22 modules**.
## Highlights
- **Undetectable by design.** Zendriver keeps a clean fingerprint; we ship a
Cloudflare Turnstile solver, identity overrides (UA, locale, timezone,
geolocation), and bezier-curve mouse movement plus gaussian typing timing.
- **Token-efficient DOM.** Two ways to see the page - the upstream DOM walker
that reports 96% fewer tokens than raw HTML, and a CDP accessibility tree
keyed by stable uids that survive re-renders.
- **Full DevTools parity.** Performance traces that load in Chrome DevTools,
heap snapshots in the standard `.heapsnapshot` format, Lighthouse audits
via the Lighthouse CLI reusing the same browser.
- **Session round-tripping.** Export all cookies (including HTTP-only ones)
to JSON, re-import on the next session. Log in once, reuse everywhere.
- **Emulation.** iPhone 15 Pro, Pixel 8, iPad Pro, and desktop presets; CPU
throttling; Slow 3G / Fast 3G / 4G / offline network profiles; force
`prefers-color-scheme`.
- **Screencasts.** Write frames to disk as JPEG or PNG at configurable FPS.
## Tool catalogue
| Module | Tools |
|---|---|
| `browser` | start, stop, status |
| `navigation` | navigate, back, forward, reload, page info |
| `tabs` | new / list / switch / close |
| `elements` | click, type, clear, focus, select, upload |
| `query` | find element(s), text, attributes, buttons, inputs |
| `content` | HTML, text, interaction tree, scroll |
| `storage` | cookies (document.cookie), localStorage |
| `logging` | network + console logs, wait-for-request |
| `forms` | fill form, submit, key press, mouse click |
| `utils` | screenshot, execute JS, wait, security audit |
| `stealth` | Cloudflare bypass, UA / locale / timezone / geolocation overrides |
| `humanlike` | human_click, human_type, estimated_typing_duration |
| `emulation` | viewport, device presets, CPU + network throttle, media |
| `devtools` | start/stop trace, take heap snapshot |
| `lighthouse` | run audit, check CLI availability |
| `screencast` | start / stop (writes frame directory) |
| `accessibility` | AX snapshot with stable uids, click_by_uid, describe_uid |
| `cookies` | export / import / list / clear (CDP-level, all origins) |
| `network_control` | block URLs, extra headers, bypass service worker |
| `permissions` | grant / reset, list names |
| `proxy` | configure / clear (restarts browser with proxy args) |
| `interception` | mock_response, fail_requests, list, stop |
| `screencast` | + export_screencast_mp4, check_ffmpeg_available |
Full signatures live in the docstrings of `src/tools/*.py` and are auto-listed
by the MCP handshake.
## Install
Published on PyPI: .
Requires Python 3.10+ and a Chrome / Chromium install.
```sh
# Zero-setup, re-resolves on every run - great for Claude Desktop configs
uvx zendriver-mcp
# Or install once, invoke many
uv tool install zendriver-mcp
pipx install zendriver-mcp
pip install zendriver-mcp
```
## Use with Claude Desktop / Claude Code
```json
{
"mcpServers": {
"zendriver": {
"command": "uvx",
"args": ["zendriver-mcp"]
}
}
}
```
No clone, no `--directory`, no absolute path. If you prefer a permanent
install instead, swap ``"command": "uvx"`` for ``"command": "zendriver-mcp"``
after running ``uv tool install zendriver-mcp``.
### Development checkout
Working on `zendriver-mcp` itself? Clone + `uv sync`, then point your MCP
client at the checkout:
```json
{
"mcpServers": {
"zendriver": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/zendriver-mcp", "run", "zendriver-mcp"]
}
}
}
```
Optional flags on the CLI:
- `--browser-path /path/to/chrome` - point at a specific Chrome binary
- `--transport stdio` - only stdio for now; SSE/HTTP arrive when upstream
`mcp` ships stable support
## The 30-second tour
```python
# Ask the browser to start, log in once, save the session.
await start_browser()
await navigate("https://example.com/login")
await fill_form({"#email": "me@me.com", "#pw": "..."})
await export_cookies("~/sessions/example.json")
# Next run: skip the login entirely.
await start_browser()
await import_cookies("~/sessions/example.json")
await navigate("https://example.com/dashboard")
# Get an accessibility snapshot, click by stable uid.
snap = await get_accessibility_snapshot()
await click_by_uid("ax_1b2c3d4e")
# Record a performance trace while you click around.
await start_trace()
await human_click(selector="#buy-now")
await stop_trace("/tmp/buy-flow.json") # loads in Chrome DevTools
# Run Lighthouse against the current browser.
await run_lighthouse("https://example.com", form_factor="mobile")
```
## Token-optimised DOM walker
The interaction tree emits compact rows like
`{"id": 1, "t": "btn", "l": "Search", "r": "hdr"}`:
- **Compact keys**: `t` (type), `l` (label), `r` (region)
- **Smart labels**: inferred from `aria-label`, `aria-labelledby`, associated
`