For the complete documentation index, see llms.txt. This page is also available as Markdown.

REST API

Base: https://unbrowse.ai/api/v1. Auth: Authorization: Bearer <API key or OAuth token>. The authenticated principal decides the workspace; a caller-supplied workspace id is never authority. MCP (/mcp) is an adapter over the same runs and authorization.

POST /runs                          { task | capability, targetUrl?, input?, interactionMode?, idempotency_key?, egress? }
GET  /runs/:id
POST /runs/:id/responses            { expected_state_revision, responses: [{ requirement_id, expected_revision, action, values }] }
POST /runs/:id/cancel
GET  /runs/:id/events
GET  /egress/:egressId               what a client-egress run waits for
POST /egress/:egressId               { requestId, response: { status, headers, body, bodyEncoding? } } | { requestId, error }
DELETE /egress/:egressId             abandon a client-egress run
POST /capabilities/search           { query }
GET  /capabilities/:id
GET  /skills
POST /learn                         { har | traces, goal?, title? } → learned.* capability
GET  /learned
GET  /learned/:id
GET  /learned/:id/harness.yaml
GET  /learned/:id/skill.md
POST /accounts/connections          { origin, username, password } → vault:// ref
POST /accounts/register             { origin, username } → generated password, vaulted
GET  /vault                         refs and audit, never secrets
GET  /logins                        saved logins as masked hints
POST /logins                        save or update one login per origin
POST /logins/remove                 { origin } | { ref }
POST /cookies                       { cookies: [{ domain, name, value, path?, secure?, expires? }] } → kept sessions
GET  /usage
GET  /me

Public (no auth):
GET  /sites?q=                      compiled sites in the public registry, with tool counts
GET  /sites/:host                   that site's tools and schemas
GET  /sites/:host/openapi.json      OpenAPI 3.1, one operation per tool
     /sites/:host/mcp               the site as its own MCP server
POST /sites/:host/call/:tool        run one tool

The idempotency key goes in the body as idempotency_key or in an Idempotency-Key header; without one the server makes its own, so a retried request starts a new run. Answers to /responses use snake_case too (requirement_id, expected_revision).

Client egress: run from your own IP

POST /runs with "egress": "client" sends the run's site requests through you, from your own IP. Unbrowse still decides every request and reads every response; it never contacts the site itself (no cloud browser, no proxy). Instead of calling the site it answers 202:

Send each request (the curl is ready to paste) and post the raw response to /egress/:egressId: { "requestId": "rq_1", "response": { "status": 200, "headers": [["content-type","application/json"]], "body": "…" } }. Headers as [name, value] pairs keep repeated ones (set-cookie); the body is decoded (after gzip/brotli), as text or base64 with "bodyEncoding": "base64", up to 10 MB. With redirect: "manual" return a 3xx as it came. If the request could not be sent (DNS, TLS, refused) post { requestId, error }. Each answer returns the next request (egress_required again) or the finished run, exactly as a server-side run returns it. 120 s per request; billing is unchanged.

Errors: { "error": { "code": "…", "message": "…" } } with an HTTP status. 402 quota_exceeded is returned before any upstream request once a workspace's monthly quota is used.

No pay-per-call

There is no x402 (crypto pay-per-call) on the hosted API: it was removed in September 2026. Every /api/v1 route except the public registry needs an API key or an OAuth token; without one, POST /runs and POST /sites/:host/call/:tool answer 401 with a WWW-Authenticate header that points to the OAuth metadata. Neither the CLI nor @unbrowse/sdk signs payments.

Supported @unbrowse/sdk methods: see sdk.md.

Last updated