Skip to content

The token‑efficient browser for agents.

One persistent browser your agent returns to turn after turn. Drive it from your own agent — skill, MCP, or JS API — or hand whole tasks to its built-in browser agent and read back one answer.

$ npm install -g betterwright
agent@betterwright — zsh

$ betterwright setup

browser ready — downloaded once, kept forever

$ betterwright run -c "await page.goto('https://example.com')"

{"ok": true, "session": "main"}

$ betterwright run -c "return page.title()"

{"ok": true, "result": "Example Domain"}

# session kept alive — logins survive turns, days, restarts

92.7%

Online-Mind2Web — 278/300 tasks

55–85%

fewer observation tokens per turn

5 turns

login → cart → checkout, vs 13

1 turn

for read-only tasks to finish

// tokens are the bottleneck

The observe step is where context windows go to die.

An agent's browser loop is observe → decide → act. Raw HTML dumps, full accessibility trees, and screenshot-only loops burn thousands of tokens per turn — tasks hit context limits and costs climb. BetterWright's whole observation stack is built around that problem:

  • Compressed agent snapshotsa distilled tree with [ref=eN] markers the model acts on directly

  • Diff modeafter an action, return only what changed — not the page again

  • Interactive-only filterdrop static text nodes; keep what the agent can click, fill, or read

  • Single-call finishread-only tasks complete in one model turn — no confirmation round-trip

  • Persistent sessionno re-login, no re-navigation, no re-paying to get back where you were

  • Sub-agent delegationa whole browsing task costs your main agent one tool call

Observation tokens per turn

12-turn browsing task · illustrative

  • Standard accessibility dump
  • BetterWright snapshots + diff

55–85% fewer tokens than a standard accessibility dump

// benchmarks

Cheap observations mean fewer turns to the same answer.

Online-Mind2Web

300 real web tasks · 278 solved

Scored by BetterWright's local strict multimodal judge — not an official leaderboard entry.

Scaffold head-to-head

Same model, same effort · 15 tasks × 3 rounds

  • BetterWright
  • Other agent scaffold

14/15 vs 12/15 correct · 10.2s vs 14.7s median · login → cart → checkout in 5 model turns vs 13.

// what's in the box

Built for agents, priced for context windows.

01

Built-in agent loop

Hand a task to betterwright exec — a browser-specialized scaffold with claude/codex/grok adapters and a pluggable model interface.

exec · console · JS API

02

Sub-agent delegation

One shell command in, one JSON object out — the whole browsing transcript stays inside the sub-agent, not your context window.

one tool call per task

03

Persistent sessions

One long-lived managed browser — no re-login, no re-navigation, no re-paying the token cost of getting back to where you were.

survives turns · days · restarts

04

Live view & handoff

Watch and coach the agent in real time. On MFA or a consequential click it pauses — you take the wheel, hit Done, it resumes.

watch · chat · take the wheel

05

CAPTCHA helpers

Local solving for checkbox, Turnstile, and slider challenges; image grids hand off to the agent's own vision with tile crops.

checkbox · Turnstile · slider

06

Proof screenshots

Tagged artifacts the agent cites as proof of work — assertions for the real web.

screenshot({ kind: 'proof' })

07

Human-shaped input

Curved pointer movement, paced typing, eased wheel — no robotic event storms.

zero extra dependencies

08

Cloaking V2 + Chromium fork

Coherent native fingerprint with per-profile-stable canvas/audio farbling, platform masking, and macOS-metric fonts.

reCAPTCHA v3 → 0.9

Plus: skill packs · interactive console · headed & headless modes

// two ways to use it

Your agent drives — or ours does.

Both modes share the same persistent sessions, snapshots, and live view — start with one and mix in the other later.

Integrated

Claude Code, Codex, Pi, any MCP client, or your own code mans the browser step by step — as one part of a bigger job. No server, no SDK, no glue code.

$ betterwright skill --install # Claude Code skill
$ claude mcp add betterwright -- npx betterwright mcp
import { BetterWright } from "betterwright"

const bw = new BetterWright()
await bw.run("await page.goto('https://example.com')", { session: "dev" })

Standalone agent

Hand over a whole browser task and read back one answer. The browser-tuned agent loop observes, acts, verifies, captures a proof screenshot, and prints one JSON object.

$ betterwright auth --login codex # OAuth, no API key
$ betterwright exec "find the top Hacker News story and give me its title and points" --model codex
A 30-turn checkout stays inside the sub-agent — it costs your main agent one tool call, not 30 pages of context.

// why not just playwright?

Playwright is built for tests. An agent is the opposite.

Tests are trusted scripts with known selectors and teardown at the end. An agent is untrusted model output deciding its next step from what it sees — in a browser that must still be there next turn.

Capability map

  • BetterWright
  • Playwright

qualitative · 0–5 per axis

  • Observations

    Playwright
    Raw accessibility tree or DIY HTML
    BetterWright
    Compressed, diffable snapshots
  • Session

    Playwright
    Browser per script
    BetterWright
    One persistent managed browser
  • Agent loop

    Playwright
    DIY scaffolding
    BetterWright
    Built-in browser-tuned agent loop
  • CAPTCHAs

    Playwright
    Out of scope
    BetterWright
    Local solve + vision handoff
  • Human in the loop

    Playwright
    Out of scope
    BetterWright
    Watch, chat, or take over on handoff
  • Evidence

    Playwright
    Assertions
    BetterWright
    Tagged proof screenshots

One browser. Every agent.

Setup downloads the browser once — never as an npm lifecycle side effect, so installs stay predictable with --ignore-scripts. Open source, MIT licensed.

01$ npm install -g betterwright

requires Node.js 22+

02$ betterwright setup

downloads the browser once (~200 MB)

03$ betterwright doctor

confirm everything resolves

then: betterwright exec "your task here" --model codex