Documentation
Everything an agent needs to drive a real browser.
One token works across MCP, A2A and the REST API. Pick your integration below — or point your agent at /llms.txt and /openapi.json and it can wire itself up.
Your first task in 60 seconds
Get a token
Sign in on /account with Google or email. Your API token (
hb_live_…) is created at once; the first top-up can be $1, about 4 typical tasks (median task $0.24). Then in your terminal:export HB_TOKEN=hb_live_…Send a task (A2A, one HTTP call)
curl -s https://agent.humanbrowser.cloud/a2a \ -H "Authorization: Bearer $HB_TOKEN" \ -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":1,"method":"message/send","params":{"message":{"role":"user","parts":[{"kind":"text","text":"Open https://news.ycombinator.com and return the top 3 story titles as JSON."}]}}}'The reply comes back within seconds, as soon as the browser is up. Open
viewerUrlto watch the agent work live and take over the mouse if you want.{ "jsonrpc": "2.0", "id": 1, "result": { "id": "t_27b88f806e7c28e6", "kind": "task", "status": { "state": "working" }, "metadata": { "sessionId": "s_…", "viewerUrl": "https://humanbrowser.cloud/a/s_…?k=…" } } }Read the result
Poll
tasks/getwith the task id every few seconds untilstatus.stateiscompletedorfailed. The answer is inmetadata.outcome.result.curl -s https://agent.humanbrowser.cloud/a2a \ -H "Authorization: Bearer $HB_TOKEN" -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":2,"method":"tasks/get","params":{"id":"t_27b88f806e7c28e6"}}'"status": { "state": "completed" }, "metadata": { "outcome": { "success": true, "result": "{\"titles\":[\"Denmark Data Breach Exposes 8.8M People's Personal Data\",\"Apple and a Hacker's Future\",\"Huawei and Qualcomm Announce Broad Patent License Agreement\"]}", "step_count": 1 }, "recordUrl": "https://humanbrowser.cloud/a/s_…?k=…&replay=1" }Prefer not to poll? Use
message/streamfor Server-Sent Events, or passcallback_urlto get the final task posted to you. Full details: A2A docs · full reference · MCP for Claude, Cursor and Codex.
Logins, pauses and errors
Pass credentials without showing them to the model
Add a data part marked sensitive, with flat string values, and write each key in the goal as a placeholder. The value is typed into the page at action time and never reaches the model, logs or results. Never put a secret in the goal text.
"parts": [ {"kind":"text","text":"Log into https://app.example.com as <email> with <password> and list my last 5 invoices as JSON."}, {"kind":"data","metadata":{"sensitive":true},"data":{"email":"[email protected]","password":"S3cret!"}} ]Answer when the agent asks (input-required)
If the agent needs an OTP or a decision, the task stops at
input-requiredwith the question inmetadata.input_required. While it is still paused, reply withmessage/sendcarryingreferenceTaskIdsandmetadata.in_reply_to; the run continues in the same browser. If the task has already ended, start a new task whose goal includes the full context and the answer.{"jsonrpc":"2.0","id":3,"method":"message/send","params":{"message":{ "role":"user","messageId":"m3", "referenceTaskIds":["t_27b88f806e7c28e6"], "metadata":{"in_reply_to":"req_…"}, "parts":[{"kind":"text","text":"493817"}]}}}Read errors instead of guessing
401bad token ·402balance used up ·-32602withgoal_rejected (…)the goal is not an instruction (empty, a${template}, or program code) — rewrite it · a failed task withmetadata.error.codecircuit_openmeans this token failed three times in 24 h on that site for the same reason (locked account, wrong password) — fix the cause ·-32601custom actions need theactions/prefix. Refusals are not billed. Onfailed, readmetadata.outcome.blocksandmetadata.postmortembefore retrying. Finished tasks stay readable for 30 minutes. Full table: llms-full.txt.