Getting started

Twin Browser is a browser execution layer for agents: you authorize a run with a key and a target URL, the engine does the work in a real browser, and repeated work gets cheap through the semantic cache. Everything below is plain REST under https://twin-browser.com/api/v1; the API reference lists every endpoint, and GET /api/v1/openapi is the same contract machine-readable.

Authentication

Every call carries Authorization: Bearer ab_live_…. Keys are per-tenant, minted in the dashboard under Keys & Secrets (the full key is shown once, at creation), and can carry scopes. The tenant is always derived from the key — never from the request body — and every run is scoped to it, metered in credits, and written to the audit log. Keys can be revoked at any time.

Your first run

A run is three things: a url (the authorization signal — you run against targets you name), a natural-language prompt, and a structured success condition the engine must satisfy for the run to count. The response carries the verified action path and exactly what was charged.

key → run → dispatch → skillbash
# Base URL: https://twin-browser.com/api/v1
# Auth: a per-tenant Bearer key (dashboard → Keys & Secrets; shown once).

curl https://twin-browser.com/api/v1/run \
  -H "Authorization: Bearer ab_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://app.acme.com/invoices",
    "prompt": "export last month as CSV",
    "success": { "kind": "urlIncludes", "value": "/exports" }
  }'

# → 200 { "success": true, "path": [ … ], "credits_charged": 10, "engineRev": "…" }

# Anything you will ask twice: same body to /dispatch — the semantic cache
# matches re-phrased requests to compiled skills and replays with no LLM:
#   HIT ~2 credits · MISS ~10 (compiles + caches for next time)

# Or manage the skill explicitly:
#   POST /skills                    { "target": "…", "goal": "…", "as": "acme-export" }
#   POST /skills/acme-export/run    → deterministic replay, ~1 credit

Pick the right endpoint

The full shapes are in the reference — this is the routing table.

  • POST /runsync · ~10 crOne-shot goal, planned live. Sign-in runs park (resumable) on 2FA walls by default.
  • POST /dispatchsync · ~2–10 crSame body as /run, fronted by the semantic cache. Default for anything you will ask twice.
  • POST /liveSSE · ~10 crSame body, but the response is a live screencast stream (meta → frame* → result), resumable mid-run.
  • POST /jobsasync · 202Background execution of the same body: poll, stream status, or get an HMAC-signed webhook.
  • POST /skills + /skills/{name}/runsync · ~50 / ~1 crCompile a goal once into a named skill, then replay it deterministically with no LLM.
  • POST /extractsync · ~5 crStructured JSON out of one page (fields or schema); free + deterministic when a template matches.
  • POST /search · /map · /crawl · /screenshotdata toolsBlended web search, site URL discovery, whole-site background crawling, page screenshots.
  • POST /etl + /etl/querypipelineScrape into a named, embedded collection; query it semantically.
  • POST /monitorsstandingWatch a page on a cadence; HMAC-signed callback on change.
  • POST /connect/sessionssessionsOne-time link your end-user opens to sign in by hand — the session is captured, the password never stored.
  • POST /secrets · GET /accountscredentialsStore credentials write-only ({{secret:NAME}}); discover which login labels already exist per host.

Credits & metering

Everything is prepaid in credits. A run reserves its ceiling up front and settles on the terminal result — a failed or empty run refunds the reserve. Charges are the higher of a flat per-action floor (run ~10, dispatch HIT ~2, skill replay ~1, extract ~5) and metered passthrough cost, and every response states credits_charged. The live rate card is at GET /pricing (no key needed) and rendered in the guide. Balance and auto top-up live in the dashboard under Settings → Billing.

Errors & result codes

Transport-level errors are conventional; the interesting signals ride inside 200 results.

  • 400Malformed body — e.g. a free-text goal in the named { target, goal } shape, or a bad success spec.
  • 401Missing or invalid API key.
  • 402Insufficient credits — top up or enable auto top-up.
  • 403Unauthorized target, missing scope, or a plan gate (code: "plan_required" — e.g. stealth runs need Pro).
  • 422Nothing to act on — e.g. /extract with no schema, fields, or matching template.
  • 429The per-account cadence governor: too many runs against the same account/host in the window. Honor Retry-After.

Inside a completed run, watch for code:

  • status: "paused"HITLA sign-in run parked on a 2FA/approval wall. Resume with POST /runs/{id}/resume + a code, drive it via /runs/{id}/input, or hand it off with a connect link. Opt out with hitl:false.
  • code: "credential_missing"+ missingSecretThe run needed a credential you have not stored — store it via POST /secrets, or send the user through POST /connect/sessions.
  • code: "connect_required"+ connectUrlAutomation cannot pass this wall. A ready one-time connect link is minted for you — hand it to your end-user; later runs restore the captured session.

The four surfaces

The same authenticated engine is reachable four ways: REST (this reference), MCP npx -y twin-browser-mcp exposes 31 tools to Cursor, Claude Desktop, Claude Code, or Cline (setup), the dashboard console (every API mode, interactive, with live streaming), and framework adapters makeTwinBrowserTools() for LangChain / AutoGen. Agents can also read /llms.txt and /api/v1/openapi directly.

Go deeper