browser-agent
🔗 Companion project:
@vernikr/browser-agent-mcp— the MCP server that exposes this daemon to LLM agents (Claude Code, Cursor, Freebuff…). The two projects are developed together and speak the HTTP contract indocs/api.md.
Real headful Chrome on Xvfb with a hardware-level X11 mouse. One localhost daemon gives any project, script, or AI agent on a Linux box a genuine desktop browser: steered over real XTEST input events on randomized Bézier paths, with zero-leak CDP (no Runtime.enable), Cloudflare Turnstile auto-solve, and RAM discipline for tiny VPSes (auto-hibernates when idle — browser-agent doctor reports what it actually costs).
Why not Playwright/CDP directly: mainstream automation stacks call Runtime.enable / Debugger.enable on connect — the primary headless-detection vector. This daemon's CDP client refuses those methods by construction and reads the DOM via DOM.getOuterHTML; all mouse/keyboard input goes through the X server, so clicks are isTrusted: true hardware events.
Install & provision (server, Ubuntu 24.04)
curl -LsSf https://astral.sh/uv/install.sh | sh # if uv is missing
uv tool install browser-agent-server
sudo browser-agent setup --with-chrome # apt deps + google-chrome-stable + systemd unit
sudo browser-agent doctor # self-check
No systemd (container, WSL, a supervisor of your own)? The same install works —
--no-unit skips the unit file and you run the daemon yourself:
uv tool install browser-agent-server
sudo browser-agent setup --no-apt --no-unit # chrome only; deps already in the image
browser-agent doctor # self-check
browser-agent serve & # foreground/background under your supervisor
Use it three ways:
browser-agent fetch "https://example.com" --text # CLI
curl -s 127.0.0.1:8765/status # HTTP API (any language)
Driving a live session over SSH needs no bridge — every action the daemon implements is a subcommand:
browser-agent goto "https://example.com" # navigate the session
browser-agent screenshot /tmp/page.png # capture the X11 window
browser-agent html # read the page back
browser-agent move 640 360 && browser-agent click 640 360
browser-agent type "hello" --submit # then press Return
browser-agent key Page_Down
browser-agent scroll --clicks 5 --direction down
from browser_agent import BrowserClient # Python SDK
client = BrowserClient()
page = client.fetch("https://example.com")
print(page["title"], len(page["text"]))
Connect from your workstation (agents)
Point the MCP bridge at this daemon — details and ready-made agent configs live in the companion repo:
pnpm dlx @vernikr/browser-agent-mcp init --client claude-code
What you get
| Capability | Detail |
|---|---|
| Real Chrome, never headless | google-chrome-stable headed on on-demand Xvfb (1280×720x24) + openbox |
| Stealth CDP | Hand-rolled RFC-6455 client; Runtime.enable/Console.enable/Debugger.enable refused by construction |
| Human-like input | X11 XTEST mouse on randomized cubic Bézier curves with ease-in/out pacing and Gaussian micro-jitter; a human-scale pause between press and release |
| Cloudflare Turnstile | Detects the interstitial, locates the checkbox via the DOM and clicks it with the real X11 mouse |
| RAM discipline | one renderer, a bounded JS heap, the tab reset after each fetch, and auto-hibernation after an idle period — see the env table for the timeout and browser-agent doctor for what it costs |
| One at a time | Global mutex: 1 tab across all callers |
| Interfaces | CLI browser-agent, HTTP API 127.0.0.1:8765, Python SDK browser_agent.BrowserClient |
| Live view | browser-agent vnc start + SSH-forwarded VNC |
| Optional WARP route | Auto-retry blocked pages through a local SOCKS5 proxy (127.0.0.1:40000) |
| Vision agent | /agent runs a screenshot→decision→X11 loop; Gemini access goes through the central gemini-router proxy (GEMINI_ROUTER_URL/GEMINI_ROUTER_TOKEN) — the daemon holds no keys. Every run leaves a full artifact directory (run_dir in the response): the exact screenshots, raw model exchanges, decisions, untruncated final text |
Docs
docs/deployment.md— provisioning, systemd, memory limits, WARP, VNC loginsdocs/api.md— HTTP contract (v1)docs/architecture.md— how and why it worksdocs/security.md— trust boundaries (loopback-only, no auth)docs/troubleshooting.md— symptom → cause → action
For AI agents
Install one-liner: uv tool install browser-agent-server && sudo browser-agent setup --with-chrome && browser-agent doctor
No-systemd host (container/WSL): uv tool install browser-agent-server && sudo browser-agent setup --no-apt --no-unit && browser-agent serve &
Self-check: browser-agent doctor --json (exit 0 = host ready; every failed check carries a fix command you can run).
Companion MCP for agent hosts: vernikr/browser-agent-mcp.
SSH-only agent, no bridge: the CLI drives the whole session — goto, move, click, type, key, scroll, screenshot, html, stop. Every one is a subcommand, so nothing needs the MCP layer to be installed.
Platform support
Linux/X11 only (Xvfb, XTEST). Works great on a 1 vCPU / 1 GB RAM VPS. macOS/Windows workstations should run the MCP bridge and talk to a Linux host running this daemon.
License
MIT — see LICENSE.
Metadata
Release files for browser-agent-server 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| browser_agent_server-1.1.0.tar.gz | 212.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| browser_agent_server-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 263.2 kB
Release files / browser_agent_server-1.1.0.tar.gz
| Download URL | browser_agent_server-1.1.0.tar.gz |
|---|---|
| Size | 212.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9aa20f29705e4f53129f0a616a55f5075c051d10df832c6769ccd03a0dbe40b3
|
|
BLAKE2b-256 checksum How to use checksums |
cc3ace62aebde37473b83f605077273d5b76b20100b023c2e9fe8335a287719d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / browser_agent_server-1.1.0-py3-none-any.whl
| Download URL | browser_agent_server-1.1.0-py3-none-any.whl |
|---|---|
| Size | 51.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b2d87ed89df839400c325e48590f72f7bb8cfbe9cc543f6ded4fad71f9b6f7f4
|
|
BLAKE2b-256 checksum How to use checksums |
26a8cdce77246f99e39b70ddd0a9faa52d06e0d35068e51cf9d5f5d61b0163bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|