Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/unbrowse-ai:unbrowse-ai-runs-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Unbrowse Ai Runs API
version: 1.0.0
contact:
name: Unbrowse
email: hello@unbrowse.ai
url: https://unbrowse.ai
termsOfService: https://unbrowse.ai/terms
description: 'Operations tagged Runs across 2 of this provider''s published API definitions: unbrowse-ai-openapi.json, unbrowse-ai-openapi2.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
- url: https://unbrowse.ai
description: Unbrowse
security:
- oauth2:
- unbrowse
- apiKey: []
tags:
- name: Runs
description: 'Do a task on a website: start, follow, answer what it needs, cancel.'
paths:
/api/v1/runs:
post:
tags:
- Runs
operationId: startRun
summary: Run a task or a capability
description: 'Routes the task to the best capability (or runs the one named), fills its inputs and replays the site''s API. Answers with the run: `succeeded` with a verified `result`, `input_required` with `requirements` to answer (POST /api/v1/runs/{runId}/responses), or `failed` with an `error`.
With `egress: "client"` the site requests are sent by you, from your own IP: the answer is `egress_required` with the next request(s) to send (method, URL, headers, body, and a ready `curl`). Send each one and post the raw response to /api/v1/egress/{egressId}; Unbrowse reads it and answers with the next request, or the finished run. Unbrowse decides every request and reads every response; it never contacts the site itself in such a run (no cloud browser, no proxy).'
parameters:
- name: x-unbrowse-deadline-ms
in: header
required: false
schema:
type: integer
minimum: 5000
maximum: 300000
default: 60000
description: Answer within this many ms (clamped to 5,000–300,000; default 60,000). Past it the answer is 504 run_timeout; the run keeps going.
- name: deadlineMs
in: query
required: false
schema:
type: integer
minimum: 5000
maximum: 300000
default: 60000
description: Same as the x-unbrowse-deadline-ms header (the header wins).
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RunRequest'
responses:
'200':
description: The run
content:
application/json:
schema:
$ref: '#/components/schemas/Run'
'202':
description: The run needs input (`input_required`), or, with egress client, the next site request to send (`egress_required`)
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Run'
- $ref: '#/components/schemas/EgressStep'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
'504':
description: 'run_timeout: the run did not finish within its deadline. It keeps running: poll `GET /api/v1/runs/{runId}` with the runId given. A verified success is billed once when it lands; a failure is never billed. A retry with the same Idempotency-Key joins the same run.'
content:
application/json:
schema:
$ref: '#/components/schemas/RunTimeout'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
/api/v1/runs/{runId}:
get:
tags:
- Runs
operationId: getRun
summary: Inspect a run
parameters:
- name: runId
in: path
required: true
schema:
type: string
description: The run id returned when the run started (run_…), or the one a run_timeout answer names (prun_…).
- name: select
in: query
required: false
schema:
type: array
items:
type: string
style: form
explode: true
description: Keep only these parts of the result (as RunRequest.select).
responses:
'200':
description: The run
content:
application/json:
schema:
$ref: '#/components/schemas/Run'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
/api/v1/runs/{runId}/events:
get:
tags:
- Runs
operationId: getRunEvents
summary: A run's event log
parameters:
- name: runId
in: path
required: true
schema:
type: string
description: The run id returned when the run started (run_…), or the one a run_timeout answer names (prun_…).
responses:
'200':
description: Events
content:
application/json:
schema:
type: object
properties:
events:
type: array
items:
$ref: '#/components/schemas/Object'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
/api/v1/runs/{runId}/responses:
post:
tags:
- Runs
operationId: answerRun
summary: Answer what a run needs
description: Supplies the missing inputs, choices or approvals a run asked for (status `input_required`), then continues it.
parameters:
- name: runId
in: path
required: true
schema:
type: string
description: The run id returned when the run started (run_…), or the one a run_timeout answer names (prun_…).
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- expected_state_revision
- responses
properties:
expected_state_revision:
type: integer
description: The run's stateRevision when you read its requirements.
idempotency_key:
type: string
responses:
type: array
items:
type: object
required:
- requirement_id
- expected_revision
- action
properties:
requirement_id:
type: string
expected_revision:
type: integer
action:
type: string
enum:
- accept
- decline
- clear
values:
type: object
additionalProperties: true
responses:
'200':
description: The run
content:
application/json:
schema:
$ref: '#/components/schemas/Run'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
/api/v1/runs/{runId}/cancel:
post:
tags:
- Runs
operationId: cancelRun
summary: Cancel a run
parameters:
- name: runId
in: path
required: true
schema:
type: string
description: The run id returned when the run started (run_…), or the one a run_timeout answer names (prun_…).
responses:
'200':
description: The run
content:
application/json:
schema:
$ref: '#/components/schemas/Run'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
/api/v1/browse-local:
post:
tags:
- Runs
operationId: startLocalBrowse
summary: Start a browser session that runs on the user's own machine
description: The agent drives the browser (open/snapshot/act/finish), but it runs locally through the CLI's `unbrowse browse --local` — the user's own browser, session and IP. What it learns is kept private to the workspace and is never shared to the public registry (the user's machine is not a trusted recorder). This is a CLI capability; a hosted MCP client cannot reach a local browser.
responses:
'201':
description: The session; connect the CLI to drive it
content:
application/json:
schema:
type: object
properties:
sessionId:
type: string
connect:
type: string
ops:
type: string
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
/api/v1/browse-local/{sessionId}/op:
post:
tags:
- Runs
operationId: localBrowseOp
summary: Issue one browse op (agent side)
description: open / snapshot / act / finish. Blocks until the connected CLI runs it in the local browser and returns the result; finish returns the learned (private) tool.
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- op
properties:
op:
type: string
enum:
- open
- snapshot
- act
- finish
url:
type: string
ref:
type: string
action:
type: string
value:
type: string
title:
type: string
responses:
'200':
description: The op result
content:
application/json:
schema:
$ref: '#/components/schemas/Object'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
/api/v1/browse-local/{sessionId}/next:
get:
tags:
- Runs
operationId: localBrowseNext
summary: 'CLI: the next op to run (long-poll)'
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
responses:
'200':
description: 'The next op, or { idle: true }'
content:
application/json:
schema:
$ref: '#/components/schemas/Object'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
/api/v1/browse-local/{sessionId}/result:
post:
tags:
- Runs
operationId: localBrowseResult
summary: 'CLI: the result of the op it ran'
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- opId
- result
properties:
opId:
type: string
result:
type: object
additionalProperties: true
responses:
'200':
description: Accepted
content:
application/json:
schema:
$ref: '#/components/schemas/Object'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
/api/v1/browse-local/{sessionId}:
delete:
tags:
- Runs
operationId: closeLocalBrowse
summary: Close a local-browse session
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
responses:
'200':
description: Closed
content:
application/json:
schema:
$ref: '#/components/schemas/Object'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
/api/v1/egress/{egressId}:
parameters:
- name: egressId
in: path
required: true
schema:
type: string
pattern: ^eg_[A-Za-z0-9_-]+$
description: From an `egress_required` answer.
get:
tags:
- Runs
operationId: getEgress
summary: What a client-egress run is waiting for
responses:
'200':
description: The finished run
content:
application/json:
schema:
$ref: '#/components/schemas/Run'
'202':
description: The next site request(s)
content:
application/json:
schema:
$ref: '#/components/schemas/EgressStep'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
post:
tags:
- Runs
operationId: answerEgress
summary: Post the site's response to a request you sent
description: Send the raw response exactly as the site gave it (status, headers, body). If the request could not be sent at all (DNS, TLS, connection refused), send `error` instead; the run treats it as a network error. You have 120 s per request.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- requestId
properties:
requestId:
type: string
response:
$ref: '#/components/schemas/EgressResponse'
error:
type: string
description: Why the request could not be sent.
responses:
'200':
description: The finished run
content:
application/json:
schema:
$ref: '#/components/schemas/Run'
'202':
description: The next site request(s)
content:
application/json:
schema:
$ref: '#/components/schemas/EgressStep'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'409':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
delete:
tags:
- Runs
operationId: closeEgress
summary: Abandon a client-egress run
responses:
'200':
description: Closed
content:
application/json:
schema:
$ref: '#/components/schemas/Object'
'400':
$ref: '#/components/responses/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/Error'
'404':
$ref: '#/components/responses/Error'
'429':
$ref: '#/components/responses/Error'
servers:
- url: https://api.unbrowse.ai
description: Unbrowse
components:
schemas:
EgressResponse:
type: object
required:
- status
properties:
status:
type: integer
minimum: 100
maximum: 599
headers:
description: As [name, value] pairs (keeps repeated headers such as set-cookie) or an object.
oneOf:
- type: array
items:
type: array
items:
type: string
minItems: 2
maxItems: 2
- type: object
additionalProperties:
oneOf:
- type: string
- type: array
items:
type: string
body:
type: string
description: The body, decoded (no content-encoding). Up to 10 MB.
bodyEncoding:
type: string
enum:
- text
- base64
default: text
url:
type: string
format: uri
description: The final URL, when redirects were followed.
RunRequest:
type: object
required:
- idempotencyKey
properties:
task:
type: string
description: What to do, in plain words. Unbrowse picks the capability.
capability:
type: string
description: A capability id to run instead of routing the task (from /api/v1/capabilities/search).
targetUrl:
type: string
format: uri
description: The site to do it on, when the task does not name one.
input:
type: object
additionalProperties: true
description: The capability's inputs.
accountRefs:
type: array
items:
type: string
description: Which kept logins to use.
interactionMode:
type: string
enum:
- interactive
- unattended
- external_handler
description: 'unattended: a check nobody can clear fails instead of waiting.'
idempotencyKey:
type: string
description: Repeat a request with the same key to get the same run.
deadlineMs:
type: integer
minimum: 5000
maximum: 300000
default: 60000
description: Answer within this many ms; past it 504 run_timeout with a runId to poll (the run keeps going). The x-unbrowse-deadline-ms header wins.
egress:
type: string
enum:
- server
- client
default: server
description: 'client: you send the site requests from your own IP (see /api/v1/egress/{egressId}).'
select:
type: array
items:
type: string
example:
- results[].{id,title,price}
- total
description: Keep only these parts of the result. Dots walk keys, [] maps over a list, [n] takes one item, a final {a,b} keeps several keys. Applied to the answer after the run is verified; billing is the same. Paths that matched nothing come back in `selectMissing`; a malformed path is a 400 invalid_input naming it. Results over 40,000 characters are shortened (`truncated`), so select what you need.
RunTimeout:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
- runId
- poll
properties:
code:
type: string
const: run_timeout
message:
type: string
runId:
type: string
description: 'Poll this id at GET /api/v1/runs/{runId} (MCP: unbrowse_inspect).'
deadlineMs:
type: integer
poll:
type: string
examples:
- GET /api/v1/runs/prun_1a2b3c
Object:
type: object
additionalProperties: true
Error:
type: object
properties:
error:
type: object
properties:
code:
type: string
message:
type: string
additionalProperties: true
additionalProperties: true
Run:
type: object
required:
- runId
- status
properties:
runId:
type: string
status:
type: string
enum:
- accepted
- working
- input_required
- succeeded
- failed
- outcome_unknown
- cancelled
- expired
capabilityId:
type:
- string
- 'null'
phase:
type: string
stateRevision:
type: integer
result:
description: The verified result (status succeeded).
requirements:
type: array
items:
$ref: '#/components/schemas/Object'
description: What the run needs (status input_required).
error:
$ref: '#/components/schemas/Object'
verified:
type: boolean
additionalProperties: true
EgressStep:
type: object
required:
- status
- egressId
- requests
properties:
status:
type: string
enum:
- egress_required
egressId:
type: string
requests:
type: array
items:
$ref: '#/components/schemas/EgressRequest'
answer:
$ref: '#/components/schemas/Object'
EgressRequest:
type: object
required:
- id
- method
- url
- headers
- redirect
- curl
properties:
id:
type: string
description: Answer with this requestId.
method:
type: string
url:
type: string
format: uri
headers:
type: object
additionalProperties:
type: string
body:
type: string
bodyEncoding:
type: string
enum:
- text
- base64
redirect:
type: string
enum:
- follow
- manual
description: 'manual: do not follow redirects; return the 3xx as is.'
curl:
type: string
description: The same request as a curl command (-i prints what to post back).
responses:
Unauthorized:
description: Missing or invalid credentials. The WWW-Authenticate header names the protected-resource metadata.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Error:
description: An error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
securitySchemes:
oauth2:
type: oauth2
description: 'Authorization code with PKCE (S256). Clients may register dynamically at /oauth/register. Discovery: /.well-known/oauth-authorization-server; the REST API''s protected-resource metadata is /.well-known/oauth-protected-resource/api.'
flows:
authorizationCode:
authorizationUrl: https://api.unbrowse.ai/authorize
tokenUrl: https://api.unbrowse.ai/oauth/token
refreshUrl: https://api.unbrowse.ai/oauth/token
scopes:
unbrowse: Run tasks and read results on the user's behalf, with their kept logins.
apiKey:
type: http
scheme: bearer
description: An Unbrowse API key (create one in the console at https://unbrowse.ai/app).
externalDocs:
description: Docs
url: https://docs.unbrowse.ai
x-refined-from:
- unbrowse-ai-openapi.json
- unbrowse-ai-openapi2.json