# brow **Repository Path**: secns/brow ## Basic Information - **Project Name**: brow - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-10 - **Last Updated**: 2026-10-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # brow — browser automation for AI agents [![CI](https://github.com/detrin/brow/actions/workflows/test.yml/badge.svg)](https://github.com/detrin/brow/actions/workflows/test.yml) [![PyPI](https://img.shields.io/pypi/v/brow-cli)](https://pypi.org/project/brow-cli/) [![Python](https://img.shields.io/pypi/pyversions/brow-cli)](https://pypi.org/project/brow-cli/) [![License: ELv2](https://img.shields.io/badge/license-Elastic%202.0-blue.svg)](LICENSE) **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](#benchmarks).** 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. ![brow demo](https://github.com/user-attachments/assets/27c6114c-451b-4e64-b66d-2268248be79b) ## Install **Homebrew:** ```bash brew tap detrin/tap brew install brow ``` **pip:** ```bash pip install brow-cli ``` Then install Chromium once (either method above): ```bash brow setup # ~150MB, one-time ``` Update patchright and its matching Chromium build later with: ```bash brow setup --upgrade ``` **Agent skill:** ```bash # 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: ```bash 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: ```bash 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 ![Google Maps search results for bars near Times Square](docs/example-maps-search.png) | Bar | Rating | Reviews | Link | |-----|--------|---------|------| | The Riff Raff Club | 4.4 | 60 | [Maps](https://www.google.com/maps/place/The+Riff+Raff+Club/) | | Ascent Lounge | 4.4 | 646 | [Maps](https://www.google.com/maps/place/Ascent+Lounge/) | | Jimmy's Corner | 4.6 | 2,195 | [Maps](https://www.google.com/maps/place/Jimmy's+Corner/) | | O'Donoghue's Times Square | 4.4 | 2,633 | [Maps](https://www.google.com/maps/place/O'Donoghue's+Times+Square/) | | The Dickens | 4.8 | 2,128 | [Maps](https://www.google.com/maps/place/The+Dickens/) | | The Woo Woo | 4.8 | 1,871 | [Maps](https://www.google.com/maps/place/The+Woo+Woo/) | 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](benchmarks/README.md) ## Commands ### Daemon ```bash brow daemon start [--port 19987] brow daemon stop brow daemon status ``` ### Sessions ```bash brow session new [--profile ] [--headed] brow session list brow session delete ``` ### Navigation ```bash brow -s navigate brow -s wait brow -s wait --load ``` ### Observation ```bash brow -s snapshot [--search ] [--locator ] brow -s screenshot [--full] [--path ] brow -s html [--locator ] [--search ] brow -s logs [--search ] [--count ] brow -s url ``` ### Interaction ```bash brow -s click brow -s fill brow -s type brow -s key # Enter, Tab, Meta+a brow -s hover brow -s scroll brow -s scroll-to brow -s drag brow -s upload ``` ### Pages ```bash brow -s page list brow -s page new [url] brow -s page close [index] brow -s page switch ``` ### Profiles & State ```bash brow profile list brow profile delete brow state save -s brow state restore -s brow state list ``` ### Eval & Run ```bash brow eval -s # inline, one-off brow run -s workflow.py --arg k=v # reusable, from a file ``` Variables available: `page`, `context`, `browser`, `state`, `pages`, plus `args` (from `--arg`) for `run`. ## 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 Elastic License 2.0 (releases <=1.2.0 remain MIT-licensed).