unbrowse · git:20260604.885548d · 2026-06-04 · sha256 f79e746a7a403a38

unbrowse git:20260604.885548dA

Immutable. This exact content is served forever at /api/v1/blob/f79e746a7a403a38.

---
name: unbrowse
description: Capture once, replay everywhere — Unbrowse learns reusable route metadata from allowed browsing sessions and replays it as a fast, cheap, indexed route. Brings back the skill surface alongside the MCP server + SDK + CLI.
metadata:
  type: integration
  origin: unbrowse-ai/unbrowse
---

# Unbrowse

Unbrowse turns websites into reusable API routes for agents. Teach a route once, store sanitized metadata, replay it on later calls. Typical run is 30× faster and 90× cheaper than a fresh browser session — peer-reviewed benchmark across 94 live domains: 3.6× mean speedup, 5.4× median, 40× fewer tokens ([arXiv:2604.00694](https://arxiv.org/abs/2604.00694)).

Four surfaces, one runtime:

| Surface | When to reach for it |
|---|---|
| **MCP server** | An MCP-host agent (Claude Desktop, Cursor, Codex, Claude Code). Tool calls like `unbrowse_resolve`, `unbrowse_execute`, `unbrowse_go` appear in the host. |
| **CLI** (`unbrowse`) | A shell session or a bash-script that wants the same surface as the MCP server, without an MCP host. |
| **SDK** (`@unbrowse/sdk`) | A TypeScript program that wants to embed Unbrowse. `npm i @unbrowse/sdk` is enough; the SDK spawns its own local binary. |
| **Drop-in shims** | One-line replace for existing tools: `@unbrowse/playwright-shim`, `@unbrowse/firecrawl-shim`, `@unbrowse/stagehand-shim`. Cache hit → free; miss → fall through to the original library. |

All four resolve to the same runtime workflow underneath:
- **resolve** asks "is there an indexed route for this intent + URL?" — returns a shortlist or a hard handoff.
- **execute** picks one endpoint from the shortlist and runs it — returns the real data.
- **browse-session** opens a managed browser when the API is too dynamic to predict; local capture indexes route metadata.

The two-tool flow (resolve + execute) is the agent UX north star: never one call, never three. The shortlist is structured so the calling LLM picks; execute is paid from the agent's wallet (or sponsored credit) when the route is priced.

## Quickstart

For an MCP host (Claude Desktop, Cursor, Claude Code, Codex):

```json
{
  "mcpServers": {
    "unbrowse": {
      "command": "npx",
      "args": ["-y", "unbrowse", "mcp"]
    }
  }
}
```

Then once:

```bash
npx unbrowse setup
```

For a shell:

```bash
unbrowse resolve --intent "search hacker news for openai" --url https://news.ycombinator.com
unbrowse execute --skill-id <id-from-resolve> --endpoint-id <id-from-shortlist>
```

For a Node program:

```bash
npm i @unbrowse/sdk
```

```typescript
import { spawn } from '@unbrowse/sdk';
const client = await spawn();
const resolved = await client.resolve({ intent: 'search hn for openai', url: 'https://news.ycombinator.com' });
const result = await client.execute({ skillId: resolved.skill.id, endpointId: resolved.endpoints[0].id });
```

## /contract-shape (why three surfaces stay coherent)

Every tool call on every surface follows the same shape:

1. **Declare** — the call carries an intent + URL.
2. **Iterate** — the runtime tries cached → marketplace → first-pass browser → live capture, in that order. Each step appends one trace row.
3. **Mark with proof** — the response carries a trace with `success`, `skill_id`, `endpoint_id`. The proof is the trace row.

Honest residue surfaces as a `next_step` field (`open_browse_session`, `abandon_or_authenticate`) instead of a one-word error.

## What lives in the public docs

Every primitive Unbrowse depends on (pointer-not-payload, residential proxy fallback, interstitial shortcut, x402+Faremeter, never-leaked-fields list, domain opt-out, fair split + claim, deploy gate, dimensional bench, kuri first-principles roadmap) is documented at [`docs/public/primitives/`](../../docs/public/primitives/) in the public repo. The README index there is enforced by `scripts/check-primitives-doc-public.sh` so the folder cannot drift from the codebase.

## Skill / MCP / SDK / CLI sync (the precommit gate)

When a shipping-surface signal changes (new top-level dir, new workspace member, new binary, new wrangler.toml target, new deploy workflow), the same commit must update a canonical doc. The gate at `scripts/precommit-doc-delta.sh` surfaces the delta as evidence on every iterate; full canonical wiring at `~/(internal)`.

The skill surface (this file) updates whenever the MCP tool catalog or the SDK API changes. The precommit gate flags it; the agent ships the update in the same commit.

## Provenance

Source code: <https://github.com/unbrowse-ai/unbrowse-dev>  
Public mirror: <https://github.com/unbrowse-ai/unbrowse>  
MCP server, CLI, SDK published from this monorepo. Backend (`backend/`) is the Cloudflare Worker that handles marketplace + sponsor tier; frontend (`frontend/`) is the landing page; `packages/skill/` is this package (the npm-published CLI binary + the skill manifest you're reading).