Skip to content

Lulzx/ubrowser

Repository files navigation

μBrowser

The fastest, cheapest browser automation for Claude.

μBrowser      ██████ 51s  $0.18
Dev Browser   ████████████████████████████████████████ 3m 53s  $0.88
Playwright    ████████████████████████████████████████████████ 4m 31s  $1.45

Benchmarks

Tested on dev-browser-eval game-tracker task with Claude Opus 4.5 (benchmark setup cloned from SawyerHood, eval tasks created independently):

Method Time Cost Turns
μBrowser 51s $0.18 7
Dev Browser 3m 53s $0.88 29
Playwright MCP 4m 31s $1.45 51

Results:

  • 5× faster than Dev Browser
  • 5× cheaper than Dev Browser
  • 8× cheaper than Playwright MCP

Latest local run (dev-browser-eval simulation, HN proxy):

Method Time Cost Turns Tokens
Traditional (6 calls) 17.36s $0.1439 6 2177
μBrowser (batch) 6.87s $0.0052 1 204

How It Works

1. Batch Execution

Combine 25+ browser actions into a single API call:

{"steps": [
  {"tool": "navigate", "args": {"url": "/login"}},
  {"tool": "type", "args": {"selector": "#email", "text": "user@test.com"}},
  {"tool": "type", "args": {"selector": "#pass", "text": "secret"}},
  {"tool": "click", "args": {"selector": "button[type=submit]"}}
], "snapshot": {"when": "final", "maxElements": 40}}

Others make 4 separate calls. We make 1. 75% fewer API calls.

2. Ultra-Compact Snapshot Format

Standard HTML (~180 tokens):

<button id="e1" role="button">Submit</button>
<input id="e2" type="email" placeholder="Email" required>
<input id="e3" type="password" placeholder="Password">

μBrowser (~50 tokens):

btn#e1"Submit"
inp#e2@e~"Email"!r
inp#e3@p~"Password"

70% smaller snapshots. Output tokens cost 5× more than input.

3. Minimal Responses

{"ok":true}
{"ok":true,"snap":"btn#e1\"Submit\"\ninp#e2@e~\"Email\""}

Only return DOM when explicitly requested.

Speed + Cost Tuning

Environment variables:

  • UBROWSER_BLOCK_STYLESHEETS=1 blocks CSS for faster loads (may affect layout-dependent pages).
  • UBROWSER_MAX_ELEMENTS=40 caps snapshots by default when maxElements is not provided.
  • UBROWSER_PROFILE_DIR=~/.ubrowser/profile browser profile directory for session persistence.
  • UBROWSER_CONSOLE_LIMIT=100 max console messages to retain in buffer.
  • UBROWSER_NETWORK_LIMIT=100 max network requests to retain in buffer.

Snapshot options (per-call overrides):

  • snapshot.maxElements limits returned elements for browser_snapshot, per-tool snapshots, and browser_batch.

Session Persistence

Browser state (cookies, localStorage, IndexedDB) persists to disk between MCP server restarts. This enables:

  • Staying logged in across sessions
  • Preserving form data and preferences
  • Maintaining shopping carts and app state

Profile stored at ~/.ubrowser/profile by default (customize with UBROWSER_PROFILE_DIR).

Implementation Details

Pre-injected extraction script — Script is injected once and JIT-cached in browser, eliminating recompilation overhead. Subsequent snapshots complete in <1ms.

Batched visibility checks — All getBoundingClientRect() calls happen in a single pass, avoiding layout thrashing that occurs with per-element checks.

MutationObserver caching — DOM changes are tracked via MutationObserver. If nothing changed, cached snapshot returns instantly (0.5ms vs 50ms).

CDP fast operations — Click and type use Chrome DevTools Protocol directly when element positions are known, bypassing Playwright's actionability checks.

Resource blocking — Images, fonts, media blocked at network level via Playwright route interception. Stylesheets preserved for layout accuracy.

Parallel snapshotPromise.all fetches URL, title, and DOM elements concurrently during batch finalization.

Single-op type — Uses fill() for instant text input when no delay/enter needed, bypassing character-by-character simulation.

Install

Claude Code Plugin (Recommended)

/plugin marketplace add lulzx/claude-code
/plugin install ubrowser@claude-code

Restart Claude Code and the ubrowser MCP tools are ready.

Manual Installation

git clone https://github.com/lulzx/ubrowser && cd ubrowser
npm install && npx playwright install chromium && npm run build
claude mcp add ubrowser -- node "$PWD/build/index.js"

Tools

Tool Purpose
browser_batch Execute multiple actions in one call
browser_navigate Go to URL
browser_click Click element by ref or selector
browser_type Type into input field
browser_select Select dropdown option
browser_scroll Scroll page or element
browser_snapshot Get interactive elements
browser_pages Manage multiple tabs
browser_inspect Deep inspect specific element
browser_console Access browser console logs
browser_network Inspect network requests

Format Reference

tag#ref@type~"placeholder"/href"content"!flags

btn#e1"Submit"           → <button>Submit</button>
inp#e2@e~"Email"!r       → <input type="email" placeholder="Email" required>
a#e3/login"Sign in"      → <a href="/login">Sign in</a>
sel#e4"Country"          → <select>Country</select>

Types: @e=email @p=password @t=text @n=number @c=checkbox @r=radio

Flags: !d=disabled !c=checked !r=required

Feature Comparison

Playwright MCP Dev Browser μBrowser
Navigate, click, type
Element refs
Multi-tab support
Session persistence
Console/network inspect
Batch execution
Compact snapshot format
Scoped snapshots partial
Diff snapshots
Configurable responses
Pre-injected scripts
MutationObserver cache
CDP fast operations

Architecture

┌─────────────────────────────────────────────────────────────┐
│                         Claude                               │
└─────────────────────────────┬───────────────────────────────┘
                              │ 1 batch call (25+ steps)
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                        μBrowser                              │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │              Batch Executor (sequential)              │   │
│  │  navigate → type → type → click → navigate → ...     │   │
│  └──────────────────────────┬───────────────────────────┘   │
│                             │                                │
│  ┌──────────────────────────▼───────────────────────────┐   │
│  │            Snapshot Engine (optimized)                │   │
│  │  ┌─────────────────────────────────────────────────┐ │   │
│  │  │ Pre-injected script (JIT cached)                │ │   │
│  │  │ MutationObserver (change detection)             │ │   │
│  │  │ Batched getBoundingClientRect (no thrashing)    │ │   │
│  │  └─────────────────────────────────────────────────┘ │   │
│  │                    ▼                                  │   │
│  │           Ultra-compact formatter                     │   │
│  │           btn#e1"Submit"\ninp#e2@e~"Email"           │   │
│  └──────────────────────────────────────────────────────┘   │
│                                                              │
└─────────────────────────────┬───────────────────────────────┘
                              │ 1 response (~50 tokens)
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                         Claude                               │
│              (continues with minimal context)                │
└─────────────────────────────────────────────────────────────┘

Performance

MCP server-side benchmarks (not including LLM response time):

Operation Time
First snapshot (cold) 4ms
Cached snapshot 0.5ms
4-step batch 34ms
Type operation 12-16ms

DOM-heavy snapshot cap (data page with 500+ interactive elements):

Mode Elements Snapshot Size (body)
baseline 100 1881 chars
maxElements=40 40 740 chars

Run locally:

node bench-game-tracker.cjs
node bench-dom-heavy.cjs

License

MIT

About

The fastest, cheapest browser automation for Claude Code.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published