Docs
Call an indexed website
Every website Unbrowse has compiled is an HTTP API: one POST per tool, typed inputs, a verified result. This page is the contract — the endpoint, auth, the answer, the options and the errors — with the same call in curl, TypeScript and Python.
What each site gives you
For a host such as docs.rs:
| What | Where |
|---|---|
| Tools, with ready-to-copy calls | GET https://unbrowse.ai/api/v1/sites/docs.rs (no key needed) |
| OpenAPI 3.1 document | GET https://unbrowse.ai/api/v1/sites/docs.rs/openapi.json (no key needed) |
| One tool | POST https://unbrowse.ai/api/v1/sites/docs.rs/call/<tool> |
| The same tools as an MCP server | https://unbrowse.ai/api/v1/sites/docs.rs/mcp |
| The page people read | https://unbrowse.ai/sites/docs.rs |
Find a site with GET /api/v1/sites?q=<words>. A site Unbrowse has not compiled yet can be learned: see the Quickstart.
The OpenAPI document
openapi.json is a complete OpenAPI 3.1 description, so any OpenAPI tool can read it:
- one operation per tool,
operationId= the tool's name; - the request body is the tool's inputs as a JSON Schema, with an
example: an input Unbrowse checked the tool with. Send it as-is for a first call that works; - the
200answer'sresultis typed from verified answers; - every status the endpoint returns (
200 202 400 401 402 404 409 422 429 504), the headers it reads, andx-codeSamplesin curl, TypeScript and Python.
Generate a client with any OpenAPI generator, for example:
npx openapi-typescript https://unbrowse.ai/api/v1/sites/docs.rs/openapi.json -o docs-rs.d.ts
Signed in (with your key), the document also lists your own tools on that site (my__…) and your organisation's (org__…). Add ?minVersion=YYYY.MM.DD to leave out tools an older Unbrowse version generated.
Auth
Every call takes your API key as a bearer token. Mint one in MCP & keys; keys start with ub_live_.
Authorization: Bearer ub_live_…
An OAuth access token (from the MCP sign-in) works the same way. With an organisation key, add X-Unbrowse-End-User: <their id> to run as one of your users, in their own workspace with their own logins.
Call a tool
The body is the tool's inputs. Nothing else is required.
curl -s 'https://unbrowse.ai/api/v1/sites/docs.rs/call/docs_rs__get_search' \
-H "authorization: Bearer $UNBROWSE_API_KEY" \
-H "content-type: application/json" \
-d '{"query":"serde"}'TypeScript, with the SDK (npm i @unbrowse/sdk):
import { Unbrowse } from "@unbrowse/sdk";
const ub = new Unbrowse(); // reads UNBROWSE_API_KEY
const run = await ub.callTool("docs.rs", "docs_rs__get_search", { query: "serde" });
if (run.status === "succeeded") console.log(run.result);Python:
import os, requests
r = requests.post(
"https://unbrowse.ai/api/v1/sites/docs.rs/call/docs_rs__get_search",
headers={"Authorization": f"Bearer {os.environ['UNBROWSE_API_KEY']}"},
json={"query": "serde"},
timeout=120,
)
r.raise_for_status()
run = r.json()
if run["status"] == "succeeded":
print(run["result"])The answer
Every call answers with the run:
{
"runId": "lrun_12meih1",
"status": "succeeded",
"capabilityId": "public.docs_rs.get_search",
"result": { "title": "…", "text": "…", "links": [{ "text": "serde", "href": "https://docs.rs/serde" }] },
"via": "http"
}status | HTTP | Meaning | Billed |
|---|---|---|---|
succeeded | 200 | result is the site's answer, verified | once |
failed | 200 | error says why (the site refused, changed, or did not answer) | never |
input_required | 202 | the tool needs a choice it found on the site: answer requirements with POST /api/v1/runs/{runId}/responses | when it succeeds |
Only verified successes bill. A tool marked x-unbrowse-personal runs signed in as you on its site: its answers are your account's.
Options
| Option | How | What it does |
|---|---|---|
| Deadline | header x-unbrowse-deadline-ms, or deadlineMs in the body (5,000–300,000; default 60,000) | Answer within this time. Past it: 504 run_timeout with a runId; the run keeps going, poll GET /api/v1/runs/{runId} |
| Retry safely | header Idempotency-Key: <your id> | A repeat with the same key returns the same run instead of starting another |
| Smaller answers | select in the body: ["results[].{title,url}", "total"] | Keep only these parts of the result. Results over 40,000 characters are shortened (truncated) |
| Act for an end user | header X-Unbrowse-End-User (organisation keys) | Runs in that user's workspace |
A tool that has an input named deadlineMs or select keeps it; the option then goes in the header (deadline) or is not available (select).
Errors
Errors answer { "error": { "code", "message" } }; the message says what to do.
| HTTP | code | What to do |
|---|---|---|
| 400 | bad_request, invalid_input | Send JSON; fix the value the message names |
| 401 | unauthorized | Send Authorization: Bearer <key> |
| 402 | quota_exceeded, insufficient_paid_credits | Out of verified calls this month, or out of paid credits: top up |
| 404 | not_found | No such tool on this site: list them with GET /api/v1/sites/<host> |
| 409 | tool_quarantined | The tool failed its checks and is rechecked automatically; the message names what to use now |
| 422 | unknown_argument | An input the tool does not take; the message lists the ones it does |
| 429 | rate_limited | Retry after Retry-After |
| 504 | run_timeout | Poll the runId it gives, or raise the deadline |
Every code: Errors & statuses.
Which tools you see
Tools are checked on a schedule. One that keeps failing is quarantined: it leaves listings and the OpenAPI document until it passes again, and calling it answers 409 tool_quarantined. A tool that needs a sign-in is offered only when your workspace has a saved login or a live session for that site.
Or use MCP
The same tools are an MCP server per site, for agents that speak MCP:
claude mcp add --transport http docs-rs https://unbrowse.ai/api/v1/sites/docs.rs/mcp
All sites at once, with discovery and the cloud browser: https://unbrowse.ai/mcp.