{"slug": "browser-cli-for-agents", "title": "Browser CLI for Agents", "summary": "A new open-source Playwright CLI tool called 'brow' achieves 82% task success at approximately $0.22 per task, outperforming browser-use, playwright-mcp, and agent-browser on 22 benchmark tasks. The tool provides a standalone Chromium instance with an agent-friendly API, persistent profiles, and structured commands for common browser actions.", "body_md": "**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.**\n\nA standalone Playwright CLI that gives your agent a real Chromium instance with an agent-friendly API — structured commands for common actions, plus an `eval`\n\nescape hatch for full power.\n\n**Homebrew:**\n\n```\nbrew tap detrin/tap\nbrew install brow\n```\n\n**pip:**\n\n```\npip install brow-cli\n```\n\nThen install Chromium once (either method above):\n\n```\nbrow setup            # ~150MB, one-time\n```\n\n**Agent skill:**\n\n```\n# For most agents (Cline, Cursor, Amp, Gemini CLI, etc.)\nnpx -y skills add detrin/brow\n\n# For OpenCode (manual install)\ngit clone https://github.com/detrin/brow.git\nln -s \"$(pwd)/brow/skills/brow\" ~/.opencode/skills/brow   # OpenCode\n```\n\nA real use case: use your Google account to search Maps in a city you've never visited, and extract structured results.\n\nOpen a headed browser with a persistent profile and sign in manually:\n\n```\nbrow session new --profile personal --headed\nbrow navigate -s 1 \"https://accounts.google.com\"\n# Sign in manually in the browser window...\nbrow session delete 1\n```\n\nYour login is saved in `~/.brow/profiles/personal/`\n\n-you won't need to sign in again.\n\nPaste this into Claude Code:\n\nOpen 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.\n\nClaude Code runs:\n\n```\nbrow session new --profile personal --headed    # → 1 (already logged in)\nbrow navigate -s 1 \"https://www.google.com/maps/search/bars+near+Times+Square+New+York\"\nbrow screenshot -s 1\nbrow eval -s 1 \"\nresults = await page.evaluate('''() => {\n    const items = document.querySelectorAll('div.Nv2PK');\n    return Array.from(items).slice(0, 8).map(el => {\n        const name = el.querySelector('.fontHeadlineSmall, .qBF1Pd');\n        const rating = el.querySelector('.MW4etd');\n        const reviews = el.querySelector('.UY7F9');\n        const link = el.querySelector('a[href*=\\\"/maps/place\\\"]');\n        return {\n            name: name?.innerText || '',\n            rating: rating?.innerText || '',\n            reviews: reviews?.innerText.replace(/[()]/g, '') || '',\n            url: link?.href || ''\n        };\n    });\n}''')\nimport json\nresult = json.dumps(results, indent=2)\n\"\nbrow session delete 1\n```\n\n| Bar | Rating | Reviews | Link |\n|---|---|---|---|\n| The Riff Raff Club | 4.4 | 60 |\n|\n\n[Maps](https://www.google.com/maps/place/Ascent+Lounge/)[Maps](https://www.google.com/maps/place/Jimmy's+Corner/)[Maps](https://www.google.com/maps/place/O'Donoghue's+Times+Square/)[Maps](https://www.google.com/maps/place/The+Dickens/)[Maps](https://www.google.com/maps/place/The+Woo+Woo/)Because the `google`\n\nprofile persists your login, you get personalized results -no cookie banners, no sign-in walls, just data.\n\n22 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).\n\n| Metric | brow |\nagent-browser | browser-use | playwright-cli | MCP Playwright |\n|---|---|---|---|---|---|\n| Success rate (16 fixture) | 88% (14/16) |\n63% (10/16) | 63% (10/16) | 50% (8/16) | 44% (7/16) |\n| Success rate (22 total) | 82% (18/22) |\n64% (14/22) | 64% (14/22) | 55% (12/22) | 36% (8/22) |\n| Avg tokens/task (16 fixture) | 68K |\n73K | 75K | 113K | 118K |\n| Avg tokens/task (22 total) | 88K | 69K |\n81K | 96K | 132K |\n| Avg tool calls | 9.6 | 11.2 | 5.8 |\n9.6 | 11.6 |\n| Avg wall-clock (fixture) | 41s | 36s |\n73s | 44s | 50s |\n| Est. cost/task | $0.22 |\n$0.23 | $0.27 | $0.35 | $0.37 |\n\nbrow 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.\n\nPer-task success grid, token breakdown, and analysis: [benchmarks/README.md](/detrin/brow/blob/main/benchmarks/README.md)\n\n```\nbrow daemon start [--port 19987]\nbrow daemon stop\nbrow daemon status\nbrow session new [--profile <name>] [--headed]\nbrow session list\nbrow session delete <id>\nbrow -s <id> navigate <url>\nbrow -s <id> wait <selector>\nbrow -s <id> wait --load\nbrow -s <id> snapshot [--search <regex>] [--locator <selector>]\nbrow -s <id> screenshot [--full] [--path <file>]\nbrow -s <id> html [--locator <selector>] [--search <regex>]\nbrow -s <id> logs [--search <regex>] [--count <n>]\nbrow -s <id> url\nbrow -s <id> click <selector>\nbrow -s <id> fill <selector> <value>\nbrow -s <id> type <text>\nbrow -s <id> key <key>            # Enter, Tab, Meta+a\nbrow -s <id> hover <selector>\nbrow -s <id> scroll <pixels>\nbrow -s <id> scroll-to <selector>\nbrow -s <id> drag <from> <to>\nbrow -s <id> upload <selector> <filepath>\nbrow -s <id> page list\nbrow -s <id> page new [url]\nbrow -s <id> page close [index]\nbrow -s <id> page switch <index>\nbrow profile list\nbrow profile delete <name>\nbrow state save <name> -s <id>\nbrow state restore <name> -s <id>\nbrow state list\nbrow -s <id> eval <code>\n```\n\nVariables available in eval: `page`\n\n, `context`\n\n, `browser`\n\n, `state`\n\n, `pages`\n\n.\n\nPlaywright selector syntax:\n\n- CSS:\n`button.submit`\n\n,`#login`\n\n- Text:\n`text=Login`\n\n- Role:\n`role=button[name=\"Save\"]`\n\n- XPath:\n`xpath=//div`\n\n```\n  ┌─────────────────────────────────────────────────────────────────┐\n  │  Agent (Claude Code, script, etc.)                              │\n  │                                                                 │\n  │  brow session new --headed          ← start browser             │\n  │  brow navigate -s 1 \"https://...\"   ← go to page               │\n  │  brow snapshot -s 1                 ← read page (a11y tree)     │\n  │  brow click -s 1 \"text=Login\"       ← interact                  │\n  │  brow fill -s 1 \"#email\" \"me@...\"   ← fill form                 │\n  │  brow screenshot -s 1               ← capture screen            │\n  │  brow eval -s 1 \"await page...\"     ← escape hatch              │\n  │  brow session delete 1              ← cleanup                   │\n  └──────────────┬──────────────────────────────────────────────────┘\n                 │ HTTP (localhost:19987)\n                 ▼\n  ┌──────────────────────────────────────┐\n  │  brow daemon (FastAPI + uvicorn)     │\n  │                                      │\n  │  ┌──────────┐  ┌──────────────────┐  │\n  │  │ Session 1 │  │ ProfileManager   │  │\n  │  │ (browser) │  │ ~/.brow/profiles │  │\n  │  ├──────────┤  └──────────────────┘  │\n  │  │ Session 2 │                       │\n  │  │ (browser) │  ┌──────────────────┐  │\n  │  └──────────┘  │ StateManager     │  │\n  │                 │ ~/.brow/states   │  │\n  │                 └──────────────────┘  │\n  └──────────────┬───────────────────────┘\n                 │ CDP (Chrome DevTools Protocol)\n                 ▼\n  ┌──────────────────────────────────────┐\n  │  Chromium (via Playwright)           │\n  │                                      │\n  │  ┌────────┐ ┌────────┐ ┌────────┐   │\n  │  │ Page 1 │ │ Page 2 │ │ Page 3 │   │\n  │  └────────┘ └────────┘ └────────┘   │\n  └──────────────────────────────────────┘\n```\n\n- Daemon auto-starts on first\n`brow`\n\ncommand - Persistent Chromium profiles for login session survival\n- One browser per session, full isolation\n- Headless by default,\n`--headed`\n\nto watch\n\n| Variable | Default | Description |\n|---|---|---|\n`BROW_HOME` |\n`~/.brow` |\nData directory |\n`BROW_PORT` |\n`19987` |\nDaemon port |\n`BROW_MAX_SESSIONS` |\n`10` |\nMax concurrent sessions |\n\n~150-300MB per Chromium instance. 10 sessions = ~2-3GB.\n\nMIT", "url": "https://wpnews.pro/news/browser-cli-for-agents", "canonical_source": "https://github.com/detrin/brow", "published_at": "2026-06-29 13:39:39+00:00", "updated_at": "2026-06-29 13:50:35.796041+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-tools"], "entities": ["brow", "Playwright", "Chromium", "Claude Code", "AWS Bedrock", "Claude Sonnet", "Google Maps", "detrin"], "alternates": {"html": "https://wpnews.pro/news/browser-cli-for-agents", "markdown": "https://wpnews.pro/news/browser-cli-for-agents.md", "text": "https://wpnews.pro/news/browser-cli-for-agents.txt", "jsonld": "https://wpnews.pro/news/browser-cli-for-agents.jsonld"}}