detrin/brow: Standalone Playwright CLI for AI agent browser automation - control real Chromium with simple comman

github.com · 2026-06-29 · by Long Nguyen ·github
Standalone Playwright CLI for AI agent browser automation - control real Chromium with simple commands, token-optimized screenshots, and reliable interactions - detrin/brow

detrin/brow

Standalone Playwright CLI for AI agent browser automation - control real Chromium with simple commands, token-optimized screenshots, and reliable interactions - detrin/brow

2 stars · 0 forks · 0 watchers · Python Topics: python, cli, web-scraping, browser-automation, ai-agents, playwright, agent-framework, llm-tools

README

brow — browser automation for AI agents

The browser tool agents win with: 82% task success at ~$0.22/task — beating browser-use, playwright-mcp, and agent-browser on 22 benchmark tasks. A standalone Playwright CLI that gives your agent a real Chromium instance with an agent-friendly API — structured commands for common actions, plus an eval escape hatch for full power.

Install Homebrew: brew tap detrin/tap brew install brow pip: pip install brow-cli Then install Chromium once (either method above): brow setup # ~150MB, one-time Agent skill:

For most agents (Cline, Cursor, Amp, Gemini CLI, etc.)

npx -y skills add detrin/brow

For OpenCode (manual install)

git clone https://github.com/detrin/brow.git ln -s "$(pwd)/brow/skills/brow" ~/.opencode/skills/brow # OpenCode Example: Find Bars Near Times Square with Google Maps A real use case: use your Google account to search Maps in a city you've never visited, and extract structured results. Step 1: Log into Google (once) Open a headed browser with a persistent profile and sign in manually: brow session new --profile personal --headed brow navigate -s 1 "https://accounts.google.com"

Sign in manually in the browser window...

brow session delete 1 Your login is saved in ~/.brow/profiles/personal/ -you won't need to sign in again. Step 2: Ask Claude Code to search Paste this into Claude Code:

Open a brow session with my personal profile, go to Google Maps, and search for bars near Times Square in New York. Return the names, Google Maps URLs, ratings, and number of reviews in a markdown table.

Claude Code runs: brow session new --profile personal --headed # → 1 (already logged in) brow navigate -s 1 "https://www.google.com/maps/search/bars+near+Times+Square+New+York" brow screenshot -s 1 brow eval -s 1 " results = await page.evaluate('''() => { const items = document.querySelectorAll('div.Nv2PK'); return Array.from(items).slice(0, 8).map(el => { const name = el.querySelector('.fontHeadlineSmall, .qBF1Pd'); const rating = el.querySelector('.MW4etd'); const reviews = el.querySelector('.UY7F9'); const link = el.querySelector('a[href*=\"/maps/place\"]'); return { name: name?.innerText || '', rating: rating?.innerText || '', reviews: reviews?.innerText.replace(/[()]/g, '') || '', url: link?.href || '' }; }); }''') import json result = json.dumps(results, indent=2) " brow session delete 1 Result

Bar Rating Reviews Link

The Riff Raff Club 4.4 60 Maps

Ascent Lounge 4.4 646 Maps

Jimmy's Corner 4.6 2,195 Maps

O'Donoghue's Times Square 4.4 2,633 Maps

The Dickens 4.8 2,128 Maps

The Woo Woo 4.8 1,871 Maps

Because the google profile persists your login, you get personalized results -no cookie banners, no sign-in walls, just data. Benchmarks 22 tasks total (16 fixture + 6 new), Claude Sonnet via AWS Bedrock. Compared against playwright-cli, MCP Playwright, agent-browser (Rust/CDP), and browser-use (full-stack agent framework).

Metric brow agent-browser browser-use playwright-cli MCP Playwright

Success rate (16 fixture) 88% (14/16) 63% (10/16) 63% (10/16) 50% (8/16) 44% (7/16)

Success rate (22 total) 82% (18/22) 64% (14/22) 64% (14/22) 55% (12/22) 36% (8/22)

Avg tokens/task (16 fixture) 68K 73K 75K 113K 118K

Avg tokens/task (22 total) 88K 69K 81K 96K 132K

Avg tool calls 9.6 11.2 5.8 9.6 11.6

Avg wall-clock (fixture) 41s 36s 73s 44s 50s

Est. cost/task $0.22 $0.23 $0.27 $0.35 $0.37

brow leads on success rate across both suites. On token efficiency, brow leads the 16-task fixture suite (68K avg) but agent-browser is most efficient across all 22 tasks (69K avg) — brow's average is inflated by one live task (github-trending-python: 383K tokens, agent didn't use snapshot filtering). browser-use runs its own agent loop — included for completeness. Per-task success grid, token breakdown, and analysis: benchmarks/README.md Commands Daemon brow daemon start [--port 19987] brow daemon stop brow daemon status Sessions brow session new [--profile <name>] [--headed] brow session list brow session delete <id> Navigation brow -s <id> navigate <url> brow -s <id> wait <selector> brow -s <id> wait --load Observation brow -s <id> snapshot [--search <regex>] [--locator <selector>] brow -s <id> screenshot [--full] [--path <file>] brow -s <id> html [--locator <selector>] [--search <regex>] brow -s <id> logs [--search <regex>] [--count <n>] brow -s <id> url Interaction brow -s <id> click <selector> brow -s <id> fill <selector> <value> brow -s <id> type <text> brow -s <id> key <key> # Enter, Tab, Meta+a brow -s <id> hover <selector> brow -s <id> scroll <pixels> brow -s <id> scroll-to <selector> brow -s <id> drag <from> <to> brow -s <id> upload <selector> <filepath> Pages brow -s <id> page list brow -s <id> page new [url] brow -s <id> page close [index] brow -s <id> page switch <index> Profiles & State brow profile list brow profile delete <name> brow state save <name> -s <id> brow state restore <name> -s <id> brow state list Eval brow -s <id> eval <code> Variables available in eval: page, context, browser, state, pages. Selectors Playwright selector syntax:

CSS: button.submit, #login Text: text=Login Role: role=button[name="Save"] XPath: xpath=//div

Architecture ┌─────────────────────────────────────────────────────────────────┐ │ Agent (Claude Code, script, etc.) │ │ │ │ brow session new --headed ← start browser │ │ brow navigate -s 1 "https://..." ← go to page │ │ brow snapshot -s 1 ← read page (a11y tree) │ │ brow click -s 1 "text=Login" ← interact │ │ brow fill -s 1 "#email" "me@..." ← fill form │ │ brow screenshot -s 1 ← capture screen │ │ brow eval -s 1 "await page..." ← escape hatch │ │ brow session delete 1 ← cleanup │ └──────────────┬──────────────────────────────────────────────────┘ │ HTTP (localhost:19987) ▼ ┌──────────────────────────────────────┐ │ brow daemon (FastAPI + uvicorn) │ │ │ │ ┌──────────┐ ┌──────────────────┐ │ │ │ Session 1 │ │ ProfileManager │ │ │ │ (browser) │ │ ~/.brow/profiles │ │ │ ├──────────┤ └──────────────────┘ │ │ │ Session 2 │ │ │ │ (browser) │ ┌──────────────────┐ │ │ └──────────┘ │ StateManager │ │ │ │ ~/.brow/states │ │ │ └──────────────────┘ │ └──────────────┬───────────────────────┘ │ CDP (Chrome DevTools Protocol) ▼ ┌──────────────────────────────────────┐ │ Chromium (via Playwright) │ │ │ │ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ Page 1 │ │ Page 2 │ │ Page 3 │ │ │ └────────┘ └────────┘ └────────┘ │ └──────────────────────────────────────┘

Daemon auto-starts on first brow command Persistent Chromium profiles for login session survival One browser per session, full isolation Headless by default, --headed to watch

Configuration

Variable Default Description

BROW_HOME ~/.brow Data directory

BROW_PORT 19987 Daemon port

BROW_MAX_SESSIONS 10 Max concurrent sessions

Resource Usage ~150-300MB per Chromium instance. 10 sessions = ~2-3GB. License MIT

source

github.com · 6 images · 134 links

Comments (0)

No comments yet