General-purpose agentic browser automation. Completes real user outcomes on any website — search, extract, fill forms, compare prices, navigate complex UIs.
- Install
- Quick Start
- How It Works
- Features
- Configuration
- CLI Reference
- SDK / Library Usage
- Examples
- Benchmarks
- Drivers
- GitHub Action
- Session Viewer
- Agent Discovery
- Development
- License
# CLI installer — installs the `bad` command, downloads Chromium, adds PATH (Node.js 20+)
curl -fsSL https://raw.githubusercontent.com/tangle-network/browser-agent-driver/main/scripts/install.sh | sh
# or via npm
npm install -g @tangle-network/browser-agent-driver
npx playwright install chromium
# as a library
pnpm add @tangle-network/browser-agent-driver
pnpm add -D playwrightDo not install the unscoped bad package from npm. It is unrelated to Tangle. The bad command is installed by @tangle-network/browser-agent-driver.
# Run a task
bad run --goal "Find the cheapest flight from NYC to London on Jan 15" \
--url https://www.google.com/travel/flights
# With vision (screenshot-based decisions)
bad run --goal "Compare MacBook Air prices" --url https://apple.com \
--observation-mode hybrid
# Test suite from case file
bad run --cases ./my-tests.json --concurrency 4import { chromium } from 'playwright'
import { PlaywrightDriver, BrowserAgent } from '@tangle-network/browser-agent-driver'
const browser = await chromium.launch({ channel: 'chrome' })
const page = await browser.newPage()
const driver = new PlaywrightDriver(page)
const agent = new BrowserAgent({
driver,
config: {
model: 'gemini-2.5-flash',
provider: 'google',
observationMode: 'hybrid', // vision + DOM
plannerEnabled: true, // plan-then-execute
},
})
const result = await agent.run({
goal: 'Find the top 3 trending repositories on GitHub',
startUrl: 'https://github.com/trending',
})
console.log(result.success, result.reason)
await browser.close()Goal → DOM Planner (1 LLM call with screenshot)
→ N deterministic steps (click, type, fill, navigate)
→ If deviation: vision per-action loop
→ Observe (a11y tree + screenshot + SoM labels)
→ LLM decides action (ref-based, coordinate, or label)
→ Execute + verify expected effect
→ Recovery on failure (strategy shift, form reset retry, search fallback)
→ Goal verification (LLM or fast-path with script evidence)
→ Complete with structured result
Recovery is automatic: cookie consent, modal blockers, A-B-A-B oscillation loops, form field resets, date picker stalls, and CAPTCHA challenges are handled before the agent continues.
- Vision + DOM Hybrid — the agent sees both a screenshot (SoM-labeled interactive elements) and the a11y tree (precise
@refIDs). Observation modes:dom(fastest),vision,hybrid(most reliable). - Stealth & Anti-Bot — system Chrome (
channel: 'chrome', real TLS/JA3 fingerprint), Patchright (CDP leak patches), Bezier mouse humanization, fingerprint hardening (webdriver, WebGL, canvas noise, screenX/Y), 99+ analytics domains blocked. Unblocks most Cloudflare/Akamai WAF setups with zero configuration. - CAPTCHA Solving — reCAPTCHA v2 (checkbox + vision-based grid solver), Cloudflare Turnstile, Google "unusual traffic". On by default:
{ captcha: { enabled: true, maxAttempts: 5 } }. - Parallel Tab Execution — compound goals ("compare X vs Y") are split by the GoalDecomposer (1 cheap LLM call) into sub-goals running in parallel tabs, merged by the EvidenceMerger:
{ parallelTabs: { enabled: true, maxTabs: 3 } }. - Multi-Model Orchestration — per-role model routing (
planner/executor/verifier/supervisor) acrossopenai,anthropic,google,claude-code,codex-cli,zai-coding-plan,cli-bridge,sandbox-backend. Roles fall back to the mainmodelwhen not configured.
Vision-powered design quality analysis with closed-loop improvement:
bad design-audit --url https://your-app.com # audit any URL
bad design-audit --url https://your-app.com --pages 10 # multi-page crawl, systemic detection
bad design-audit --url http://localhost:3000 --evolve claude-code --project-dir ~/my-app # auto-fixReports rank Top Fixes by ROI — the highest-leverage changes scored by (impact * blast / effort).
A built-in MetaMask workflow for teams testing DeFi apps — a deliberate specialization, not the general-purpose path:
pnpm wallet:setup # download MetaMask
pnpm wallet:onboard # automate first-run wizard
pnpm wallet:anvil # start Anvil mainnet fork (100 ETH + 10 WETH + 10k USDC)
pnpm wallet:validate # run wallet test suiteSupports connect, swap, supply workflows across Uniswap, Aave, SushiSwap, 1inch. See the wallet guide.
Create bad.config.ts (or .js, .mjs) in your project root:
import { defineConfig } from '@tangle-network/browser-agent-driver'
export default defineConfig({
model: 'gemini-2.5-flash',
provider: 'google',
observationMode: 'hybrid',
plannerEnabled: true,
headless: true,
concurrency: 4,
maxTurns: 30,
outputDir: './test-results',
})Auto-detected by CLI and SDK. CLI flags override config values.
The default provider is credential-aware: with no explicit provider, bad uses OpenAI when OPENAI_API_KEY is set and otherwise falls back to the keyless claude-code provider. The bench-validated default model is gemini-2.5-flash (Google) — see Benchmarks. Key options:
| Option | Default | Description |
|---|---|---|
provider |
credential-aware | openai if OPENAI_API_KEY set, else claude-code |
model |
per-provider | LLM model (gemini-2.5-flash is the bench-validated choice) |
observationMode |
'dom' |
'dom', 'vision', or 'hybrid' |
plannerEnabled |
false |
Plan-then-execute mode |
maxTurns |
30 |
Max turns per task |
proxy |
— | Proxy URL (also BAD_PROXY_URL env) |
models |
— | Per-role model overrides |
See Configuration Reference for all options.
bad run [options] # Run tasks
bad snapshot --url <url> # Headless accessibility-tree dump (no LLM)
bad design-audit [options] # Design quality analysis
bad view <run-dir> # Open session viewer
bad competitive [options] # Head-to-head framework comparisonFull flag reference (run modes, execution profiles, auth sessions, adaptive model routing): docs/guides/cli.md.
import {
BrowserAgent,
PlaywrightDriver,
SteelDriver,
TestRunner,
MultiActorSession,
defineConfig,
DesignAuditor,
detectCaptcha,
solveCaptcha,
type AgentConfig,
type Scenario,
type AgentResult,
} from '@tangle-network/browser-agent-driver'Runnable recipes live in examples/: SDK quickstart, authoring a bench task, replay-cache CI, the GitHub Action, and shareable run videos.
Current bench (2026-10-11, gemini-2.5-flash, headless, external oracle, 5-task competitive corpus × 3 reps + n=5 variance arm): 15/15 main + 10/10 arm, $0.0223/run, 17.9s wall, 30% replay-cache hit rate. browser-use on the same corpus: 12/15 @ $0.0126/run. Cost ratio 1.8×, accepted asymptote 1.3–1.6× (1.0× would sacrifice extraction accuracy and the replay moat). Replay-cache reruns cost ~10–20% of a live run with zero decide calls. Full methodology: docs/bench-2026-10-11-hillclimb-program.md; competitive evaluation: docs/COMPETITIVE-EVAL.md.
Run it:
pnpm bench:competeThe agent loop is decoupled from the browser via the Driver interface:
// Local Playwright (default)
const driver = new PlaywrightDriver(page)
// Steel cloud browser (anti-bot, residential proxies, CAPTCHA)
const driver = await SteelDriver.create({
apiKey: process.env.STEEL_API_KEY,
sessionOptions: { useProxy: true, solveCaptcha: true },
})
// Any Driver implementation works
const agent = new BrowserAgent({ driver, config })- uses: tangle-network/browser-agent-driver/.github/actions/design-audit@main
with:
url: ${{ steps.deploy.outputs.preview_url }}
pages: 5
fail-on-score-below: '6.5'
evolve: claude-codePosts Top Fixes as a PR comment, uploads the full report as an artifact, optionally fails on score regressions.
bad view audit-results/stripe.com-1775502457141Web UI with per-turn screenshots, action JSON, reasoning, element highlights. A run's report.json is also a complete trace that renders into a shareable video via run-capsule — see examples/run-capsule.md.
Agents integrating Browser Agent should start from the live manifest at https://browser.tangle.tools/llms.txt. The same discovery manifest (llms.txt + tangle-agent.json) ships in the npm package under discovery/.
pnpm build # TypeScript → dist/
pnpm test # vitest suite (~2,000 assertions across 174 files)
pnpm lint # type-check
pnpm check:boundaries # architecture boundariesPublishing is automated via Changesets + OIDC trusted publishing: add a changeset with pnpm changeset, merge the release PR, npm publish fires with provenance attestation.
Dual-licensed under MIT and Apache 2.0. See LICENSE.