Skip to main content
Glama

agent-headless-browser

CI Python License: MIT

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 needed

Why 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-view streams 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 | sh

Windows, in PowerShell:

iwr -useb https://raw.githubusercontent.com/EgiStr/agent-headless-browser/main/scripts/install.ps1 | iex

Or 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         # Windows

It 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 | sh

The 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 stop

On 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 stop

2. 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 dies

3. 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-mcp

Clients 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

browser_status

Whether Chrome is running and headless, and which Google accounts are signed in

browser_start / browser_stop

Start or stop Chrome; stop is graceful, so cookies reach disk

login_begin / login_finish

Re-login: opens a window on desktops, or gives login-view steps on servers; finish verifies the account and goes back to headless

navigate, page_snapshot, click, type_text, press_key, screenshot, evaluate

General browsing; page_snapshot returns numbered refs for click and type_text

looker_export

Every row of each datasource behind a Looker Studio report, written to CSV

health_check

Checks the session still works and appends to session_health.jsonl

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

AHB_PORT

9333

CDP port; Chrome always binds 127.0.0.1

AHB_PROFILE_DIR

~/.agent-headless-browser/profile

The live login. Back it up like a password, never copy it to run elsewhere

AHB_OUT_DIR

out

Exports and the health log

AHB_CHROME_ARGS

Extra Chrome flags, e.g. --no-sandbox inside a container

AHB_HEALTH_URL

https://myaccount.google.com/

Page used by ahb health; a Looker URL also waits for its data call

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

docs/architecture.md

How the pieces fit, what lives on disk, where to add a tool

docs/mcp-tools.md

You are calling the tools: exact signatures, return shapes, error strings

docs/looker-export.md

You are exporting a report, or a number looks wrong

docs/troubleshooting.md

Something failed: symptom → cause → fix

docs/development.md

You are changing the code or cutting a release

docs/vps.md

You are running it on a server with no display

docs/findings.md

You want to know why the design is like this; it is the experiment log

AGENTS.md

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 . && mypy

See 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

MIT

Available Tools

14 tools
browser_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

    B3.4/5.0

    Scored across 14 tools

    Disambiguation4/5

    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.

    Naming Consistency3/5

    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.

    Tool Count5/5

    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.

    Completeness4/5

    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

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables 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.
      12
      MIT
    • A
      license
      B
      quality
      D
      maintenance
      Enables 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.
      20
      244
      MIT
    • A
      license
      B
      quality
      D
      maintenance
      Enables AI agents to fully control Google Chrome: navigate, click, fill forms, inspect DevTools, and manage tabs with parallel execution and session isolation.
      24
      6 npm
      MIT
    • A
      license
      A
      quality
      A
      maintenance
      Enables 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.
      40
      62
      MIT