agent-browser
Maintains a long-lived signed-in Google account session in a dedicated Chrome profile, enabling agents to check signed-in accounts, navigate Google services, and keep the session healthy across restarts.
Controls a headless Google Chrome instance over CDP, providing tools for navigation, page snapshots with numbered refs, clicking, typing, key presses, screenshots, and JavaScript evaluation.
Exports all rows from each datasource behind a Looker Studio report to CSV by capturing and replaying batchedDataV2 requests, expanding counts, and re-inserting nulls.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agent-browser export every row behind my Looker Studio report to CSV"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
agent-headless-browser
A headless Chrome for AI agents that stays signed in to your own Google account and runs 24/7 on a laptop or a CLI-only Linux server. It is exposed as an MCP server and ships with a Claude Code skill. One of its tools exports every row behind a Looker Studio report to CSV.
AI agent (Claude Code or any MCP client)
│ stdio
ahb-mcp ──── 14 tools ────┐
│ CDP, 127.0.0.1 only │
ahb start ─► one long-lived Chrome ─► profile dir (your Google session)
▲
ahb login-view ───┘ live click-and-type view for the one-time sign-in; no X server neededWhy it works this way
The research log has the details. In short:
Copied profiles and exported cookies no longer work for Google. Since Chrome 146, Google sessions are bound to the device (DBSC, a TPM-held key). Transplanted cookies land on the account chooser, headless or headful.
The fix is to sign in once inside a dedicated agent profile with DBSC disabled. The agent then reuses that profile, headless.
One Chrome process owns the profile for its whole life, and agents attach over CDP. In testing, a copied profile folder and injected cookies both failed; which step killed the session was never isolated, so both are off limits.
A server without a display can complete the sign-in.
ahb login-viewstreams the headless tab to your browser through an SSH tunnel. This was tested in a display-less Debian container: sign-in, restart, and a 212k-row export.
Related MCP server: agent-browser-mcp
Install
Needs Google Chrome (not Chromium). Python 3.10+ is used when the machine has one; the installer can also bring its own.
One click
macOS or Linux:
curl -fsSL https://raw.githubusercontent.com/EgiStr/agent-headless-browser/main/scripts/install.sh | shWindows, in PowerShell:
iwr -useb https://raw.githubusercontent.com/EgiStr/agent-headless-browser/main/scripts/install.ps1 | iexOr clone the repo and double-click scripts\install.cmd.
The installer checks the prerequisites, installs the package with uv (or
pipx, or pip), registers the MCP server with the Claude Code and DSH
profiles it finds on the machine, and prints the sign-in steps. It never signs
in for you: that step is yours.
To see what it would do without changing anything:
python3 scripts/install.py --dry-run # macOS or Linux
py scripts/install.py --dry-run # WindowsIt is safe to run again after an update, and it reuses an agent Chrome that is already running instead of starting a second one.
Pinning the bootstrap
The one-liners above fetch main, which is a moving target: whatever sits on
main at that moment runs with your privileges. If you want a fixed copy,
point the installer at a commit instead:
curl -fsSL https://raw.githubusercontent.com/EgiStr/agent-headless-browser/<commit>/scripts/install.sh | shThe same works for the PowerShell one-liner. The script is short, and the whole
install lives in scripts/install.py, so it is worth a
read before you run it.
By hand
pipx install git+https://github.com/EgiStr/agent-headless-browser
# or, from a clone: pip install -e ".[dev]"Then point an MCP client at it, for example
claude mcp add -s user agent-browser -- ahb-mcp. A ready-to-copy config is in
mcp.example.json.
Usage
1. Sign in once
ahb start --headful # desktop: sign in in the window that opens
ahb stopOn a CLI-only server:
ahb start --login # headless Chrome on the Google sign-in page
ahb login-view # live view on 127.0.0.1:9500
# on your PC: ssh -N -L 9500:127.0.0.1:9500 user@server then open http://127.0.0.1:9500
ahb stop2. Run headless
ahb start # CDP on 127.0.0.1:9333
ahb status # {"running": true, "headless": true, "google_accounts": ["you@..."]}
ahb health --every 1800 # exits 1 and logs "ok": false if the session dies3. Use it
ahb looker-export https://lookerstudio.google.com/reporting/<report-id> --out exports/To run it as a service, see docs/vps.md. It covers systemd units and sizing.
MCP server
claude mcp add -s user agent-browser -- ahb-mcpClients that read a JSON config can copy mcp.example.json and adjust the paths. The variable
names in it are the ones the server actually reads: a name the server does not know is ignored without a warning, so
a hand-written config with a stale name quietly falls back to the defaults.
ahb-mcp has to be on the client's PATH. A client that spawns the server with an environment of its own, instead of
inheriting the parent's, may not find it on Windows: point command at the absolute path of ahb-mcp.exe, or at
python with the args -m agent_headless_browser.mcp_server.
Tool | What it does |
| Whether Chrome is running and headless, and which Google accounts are signed in |
| Start or stop Chrome; stop is graceful, so cookies reach disk |
| Re-login: opens a window on desktops, or gives |
| General browsing; |
| Every row of each datasource behind a Looker Studio report, written to CSV |
| Checks the session still works and appends to |
The skill in .claude/skills/agent-browser tells agents to check status first,
never to type credentials, and never to copy the profile.
Configuration
Variable | Default | |
|
| CDP port; Chrome always binds 127.0.0.1 |
|
| The live login. Back it up like a password, never copy it to run elsewhere |
|
| Exports and the health log |
| Extra Chrome flags, e.g. | |
|
| Page used by |
How looker_export works
It opens the report as you and captures one real batchedDataV2 request. It then replays that request from inside the
page with all dimensions plus Record Count, sorted on every dimension, 50k rows per page. Counts are expanded back
into raw rows, and nulls are re-inserted from nullIndex. It sees only what you can see as a viewer, and only the
datasources used on the page you open. It depends on undocumented endpoints, so expect breakage when Google changes them.
Documentation
Document | Read it when |
How the pieces fit, what lives on disk, where to add a tool | |
You are calling the tools: exact signatures, return shapes, error strings | |
You are exporting a report, or a number looks wrong | |
Something failed: symptom → cause → fix | |
You are changing the code or cutting a release | |
You are running it on a server with no display | |
You want to know why the design is like this; it is the experiment log | |
You are an agent working in this repository |
Benchmark
Same tasks as dev.to "16MB vs 1.2GB". Full table and method: docs/benchmark.md.
Linux CLI | Article range (5 tools) | |
httpbin open + snapshot + close | 0.76 s | 0.45 – 4.91 s |
1 page, unique RAM (USS) | 245 MB | not reported (RSS 16 – 1,202 MB) |
3 parallel tabs | 1.01 s | 4.9 – 10.6 s |
Signed-in Looker export, 212k rows | 99 s | not tested by any of them |
Development
pip install -e ".[dev]" && pre-commit install
pytest # unit tests, no browser
AHB_E2E=1 pytest -m integration # real Chrome, no network or Google account needed
ruff check . && ruff format --check . && mypySee CONTRIBUTING.md.
Security and responsible use
CDP gives full control of the signed-in Google account. Keep port 9333 on 127.0.0.1 and reach it only through SSH, and treat the profile directory as a credential. This tool is for automating your own account and data you are allowed to see. Respect Google's Terms of Service and the sharing settings of any report you export. To report a vulnerability, see SECURITY.md.
License
Available Tools
14 toolsbrowser_startB
Start the long-lived agent Chrome (headless by default) on the agent profile.
Inputs: headful. Returns: result
browser_statusA
Is the agent Chrome running, headless or not, and which Google accounts are signed in.
Inputs: no named parameters. Returns: object
browser_stopA
Gracefully close the agent Chrome so rotated cookies are written to the profile.
Inputs: no named parameters. Returns: result
clickC
Click an element by page_snapshot ref or Playwright selector (css=, text=, role=...).
Inputs: ref, selector. Returns: object
evaluateC
Run a JavaScript expression or function in the agent tab; returns the result as JSON.
Inputs: script (required). Returns: result
health_checkB
Load a page that needs the Google session and report whether it still works.
For a Looker Studio URL it waits for the report's data call. Appends to /session_health.jsonl.
Inputs: url. Returns: object
login_beginA
Open the Google sign-in page for a human. The agent must never type credentials.
With a display: a visible Chrome window. Without one (CLI server): headless, signed in through
ahb login-view. Call login_finish afterwards.
Inputs: no named parameters. Returns: result
login_finishB
Verify the sign-in worked, then restart the agent Chrome headless on the same profile.
Inputs: no named parameters. Returns: object
looker_exportA
Export every row of each datasource behind a Looker Studio report to CSV.
Only datasources used on the opened page are seen; for multi-page reports call it per page URL.
Inputs: report_url (required), out_dir, page_size. Returns: object
page_snapshotB
Visible text plus numbered interactive elements of the agent tab, for click/type_text refs.
Inputs: max_elements. Returns: object
press_keyB
Press a key in the agent tab, e.g. Enter, Escape, PageDown, Control+A.
Inputs: key (required). Returns: result
screenshotC
PNG screenshot of the agent tab.
Inputs: full_page.
type_textB
Fill a field by ref or selector; submit=True presses Enter. Never use it for passwords.
Inputs: text (required), ref, submit, selector. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 14 tools
Each tool has a distinct role: lifecycle (browser_start/stop/status), auth (login_begin/login_finish/health_check), and page interaction (navigate, page_snapshot, click, type_text, press_key, evaluate, screenshot). Minor overlap exists — health_check essentially performs a navigate plus session validation, browser_status overlaps somewhat with health_check's session reporting, and login_finish restarts Chrome much like browser_start — but descriptions make the intended use of each clear. looker_export is clearly scoped apart from generic page tools.
All names are snake_case, but verb/noun ordering is mixed: verb-first (navigate, click, evaluate, screenshot) alongside noun-first compounds (page_snapshot, looker_export, browser_start, login_begin, health_check). Related families are internally consistent (browser_*, login_*), yet 'page_snapshot' vs 'screenshot' shows inconsistent vocabulary for adjacent concepts. Readable overall, but not a single predictable pattern.
14 tools is well within a sensible range for a browser-automation server and each one covers a genuine capability: lifecycle, auth handoff, navigation, inspection, four interaction primitives, plus one domain-specific export helper. Nothing appears redundant enough to remove.
The core browsing loop (start → navigate → snapshot → click/type/press → screenshot/evaluate → stop) plus human Google sign-in is covered end to end. Gaps are minor: no tab listing/switching or back/forward history, no explicit wait-for-element or hover/select helpers, and no download/upload handling — though press_key and evaluate provide workarounds.
Maintenance
Related MCP Connectors
Let AI agents use your real, signed-in Chrome: tabs, clicks, forms, screenshots and video.
Give AI agents a real cloud Chrome: open sessions, navigate, read pages, click, type and screenshot.
Let your AI agent operate any website through a real, logged-in browser session.
Connect AI agents to your own Chrome with scoped access, approvals, and verified task results.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to control and automate your Chrome browser directly, leveraging existing login states and configurations for tasks like content analysis, semantic search across tabs, screenshots, network monitoring, and interactive operations.12MIT
- AlicenseBqualityDmaintenanceEnables AI agents to directly control your real Chrome browser with full context including login sessions, cookies, and open tabs. It provides tools for page scanning, JavaScript execution, CDP control, screenshots, and physical mouse/keyboard input for authentic browser automation.20244MIT
- AlicenseBqualityDmaintenanceEnables AI agents to fully control Google Chrome: navigate, click, fill forms, inspect DevTools, and manage tabs with parallel execution and session isolation.246 npmMIT
- AlicenseAqualityAmaintenanceEnables AI agents to drive your real, logged-in Chrome browser with existing sessions and cookies, bypassing CAPTCHA and anti-bot measures, with support for multi-session and human-in-the-loop workflows.4062MIT