WebBrain Cloud API

Your code asks.
A real browser does.

Launch a private Chrome browser, watch every action live, and keep control through REST or a small dependency-free client.

Base URLhttps://webbrain.cloud
browser_session / live trace Visible

POST/api/browser-sessions/:id/runs

  1. session.createdPrivate Chrome allocated
  2. runtime.readyExtension bridge connected
  3. run.workingOpening example.com
  4. run.completed
    Result returned to your code

    { "title": "Example Domain" }

Choose the shortest path for your setup

Five-minute quickstart

From API key to result

Create one browser, wait for its runtime, start one visible task, and read the result. The browser remains available for follow-up runs until you pause or destroy it.

01 / CreateLaunch ChromeReceive a browser session ID.
02 / ReadyWait for the bridgePoll until runtime_ready is true.
03 / RunDescribe the taskStart an asynchronous visible run.
04 / ResultRead the outcomePoll for text or structured JSON.
export WEBBRAIN_API_KEY='wbp_your_key_here'

# 1. Create a browser
SESSION_ID=$(curl -sS -X POST https://webbrain.cloud/api/browser-sessions \
  -H "Authorization: Bearer $WEBBRAIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type":"normal"}' | jq -r '.browser_session.id')

# 2. Wait for the extension bridge
until [ "$(curl -sS \
  "https://webbrain.cloud/api/browser-sessions/$SESSION_ID" \
  -H "Authorization: Bearer $WEBBRAIN_API_KEY" \
  | jq -r '.browser_session.runtime_ready')" = "true" ]; do sleep 2; done

# 3. Start a visible run
RUN_ID=$(curl -sS -X POST \
  "https://webbrain.cloud/api/browser-sessions/$SESSION_ID/runs" \
  -H "Authorization: Bearer $WEBBRAIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"task":"Open google.com and return the page title"}' \
  | jq -r '.run_id')

# 4. Read the result
curl -sS \
  "https://webbrain.cloud/api/browser-sessions/$SESSION_ID/runs/$RUN_ID" \
  -H "Authorization: Bearer $WEBBRAIN_API_KEY" | jq

Every API request uses Authorization: Bearer $WEBBRAIN_API_KEY. Keep the key in your environment or secret manager—never in source control.

Mental model

Four objects, one visible browser

WebBrain separates the browser you rent from the work you ask it to do. Create a browser session once, send it many runs, and turn a successful run into a reusable workflow when the steps should repeat exactly.

browser_sessionThe remote Chrome browser

Owns its profile, lifecycle, proxy state, downloads, and live noVNC view.

runtime_readyThe safe-to-run signal

Wait for this boolean before dispatching work. A created Droplet is not yet a connected browser.

runOne automation turn

Contains a task, its status, updates, final result, and optional request for user input.

workflowA replayable success

Compiles a completed trace into a sanitized definition with validated parameters.

The reliable loop: create or reuse a session → wait for runtime_ready → start a run → poll until terminal → continue with another run or clean up the browser.

Access

Authenticate every request

API keys belong to one account and can control only that account's browsers, runs, workflows, and files. The complete key is displayed once when it is created.

  1. Create a keyOpen the dashboard's API Keys panel and copy the new wbp_… secret.
  2. Store it outside codeSet WEBBRAIN_API_KEY in your environment or secret manager.
  3. Send a Bearer headerInclude Authorization: Bearer … on every API call.
If a key is exposed: revoke it from the dashboard and create a replacement. Do not put keys in prompts, screenshots, client-side JavaScript, URLs, or tracked files.

Lifecycle

Choose the browser that fits the job

A browser session is a private Chrome environment with its own profile, network state, files, and automation bridge. Both browser types remain until you explicitly destroy them.

IncognitoSimple and always running

Keeps Chrome and Downloads on one running Droplet. Pause is unavailable; destroy it when the work is finished.

Readiness has two stages: wait for the session status to become ready, then confirm runtime_ready: true. The second signal means the WebBrain extension bridge is connected.

POST /api/browser-sessions request body

An empty JSON object is valid and creates a normal browser. Infrastructure placement, Droplet size, proxy credentials, and the reserved WebBrain Cloud connection are private server configuration and cannot be overridden by this request.

FieldTypeDefaultApplies toPurpose
display_namestringNoneBothAn optional dashboard label up to 120 characters.
typestring enumnormalBothnormal or incognito, matching the dashboard.
proxy_enabledbooleanServer defaultBothtrue uses the server-configured proxy; false uses a direct connection.
proxy_countrystringrotateBothOptional country or region code (e.g. us, de) passed when proxy_enabled is true. Substituted into % template placeholders in server proxy URLs, falling back to rotate if omitted or unconfigured.
webbrain_configwebbrain-config/1 objectNoneBothOptional sparse Settings import copied directly from WebBrain's /export --config output.

DigitalOcean region and size come only from DO_REGION and DO_SIZE. Proxy routing and credentials come only from the server's proxy environment. They are intentionally absent from the public request body.

Import WebBrain Settings at creation

Paste the complete JSON produced by WebBrain's /export --config command into webbrain_config. The export metadata is accepted unchanged. Settings are sparse: omitted fields keep their normal WebBrain or cloud defaults, accepted fields are applied before runtime_ready, and invalid or managed fields are ignored without failing browser creation.

Editable fields are wbLocale, themeMode, verboseMode, selectionShortcutEnabled, helpImproveWebBrain, voiceInputEnabled, notifySound, completionConfetti, providerFilter, screenshotFallback, autoScreenshot, useSiteAdapters, apiMutationObserverEnabled, screenshotRedaction, the agent/cost limits, captchaSolverEnabled, capsolverApiKey, providers, and activeProvider.

WebBrain Cloud connection fields, plan/review policy, tracing, permissions, Downloads path, local-network access, schedules, profile, memory, and custom skills remain platform-managed. Additional providers are merged, but private/local endpoints are ignored and the reserved webbrain_cloud connection always keeps its platform-issued URL, model, and session token. A valid configured external provider may be selected with activeProvider.

Config exports contain plaintext provider and CapSolver API keys. Send them only over HTTPS, never log the request body, and remember that normal browsers retain accepted settings on their profile volume while incognito settings disappear when the browser is destroyed.

export WEBBRAIN_API_KEY='wbp_your_key_here'

curl --fail-with-body -sS -X POST \
  https://webbrain.cloud/api/browser-sessions \
  -H "Authorization: Bearer $WEBBRAIN_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON' | jq '.webbrain_config_result'
{
  "type": "incognito",
  "webbrain_config": {
    "schema": "webbrain-config/1",
    "settings": {
      "captchaSolverEnabled": true,
      "capsolverApiKey": "replace-with-your-key",
      "activeProvider": "webbrain_cloud"
    }
  }
}
JSON

Config import result

When webbrain_config is supplied, the create response includes accepted field paths, ignored fields with stable reason codes, non-secret warnings, and the security settings actually enforced by the managed runtime. Values and credentials are never echoed.

201 Created · application/json
{
  "browser_session": {
    "id": "bs_example",
    "status": "provisioning"
  },
  "webbrain_config_result": {
    "accepted": [
      "settings.captchaSolverEnabled",
      "settings.capsolverApiKey",
      "settings.activeProvider"
    ],
    "ignored": [
      {
        "field": "settings.planBeforeActMode",
        "reason": "platform_managed"
      }
    ],
    "warnings": [],
    "enforced": {
      "strictSecretMode": true,
      "scheduledRequireConsequentialConfirmation": false
    }
  }
}
POST/api/browser-sessionsCreate a normal or incognito browser.
GET/api/browser-sessionsList your sessions.
GET/api/browser-sessions/:sessionIdRead readiness.
PATCH/api/browser-sessions/:sessionIdSet its display name.
GET/api/browser-sessions/:sessionId/proxyRead proxy and exit IP.
PATCH/api/browser-sessions/:sessionId/proxyEnable or disable the server-configured proxy without restart.
DELETE/api/browser-sessions/:sessionId/proxyReturn to a direct connection.
POST/api/browser-sessions/:sessionId/resetRestart the running browser.
POST/api/browser-sessions/:sessionId/pauseStop the Droplet and retain the profile.
POST/api/browser-sessions/:sessionId/resumeAttach the profile to a new Droplet.
DELETE/api/browser-sessions/:sessionIdDestroy the browser and its infrastructure.
POST/api/browser-sessions/:sessionId/connect-tokenCreate a noVNC link.
POST/api/browser-sessions/:sessionId/downloads-accessCreate private Downloads credentials.

Copy and adapt

Create and run in your language

These examples create a named normal browser with a direct connection, wait until its runtime is ready, run one visible task, and print the result. The bundled clients have no third-party runtime dependencies.

import { WebBrainClient } from './clients/node/webbrain-client.js';

const client = new WebBrainClient({
  apiKey: process.env.WEBBRAIN_API_KEY,
});

const session = await client.createBrowserSession({
  display_name: 'Research browser',
  type: 'normal',
  proxy_enabled: false,
});

const ready = await client.waitForBrowserSession(session.id);
const run = await client.createRun(ready.id, {
  task: 'Open example.com and return the page title',
});
const finished = await client.waitForRun(ready.id, run.run_id);

console.log(finished.result);

File transfer

Upload and download files

For a ready or paused browser, request access metadata from POST /api/browser-sessions/:sessionId/downloads-access. The response contains an HTTPS url, username, password, upload_limit_bytes, and expires_at. It is returned with Cache-Control: no-store; do not log it.

Treat download access like a temporary password. Request it only when needed, keep the returned credentials out of logs, and use the exact expiry time rather than assuming the link remains valid.
# Obtain access and keep the secret out of the literal shell history
DOWNLOADS_ACCESS=$(curl --fail-with-body -sS -X POST "https://webbrain.cloud/api/browser-sessions/$SESSION_ID/downloads-access" -H "Authorization: Bearer $WEBBRAIN_API_KEY" -H "Content-Type: application/json" -d '{}')
DOWNLOADS_URL=$(printf '%s' "$DOWNLOADS_ACCESS" | jq -r '.url')
DOWNLOADS_USER=$(printf '%s' "$DOWNLOADS_ACCESS" | jq -r '.username')
DOWNLOADS_PASSWORD=$(printf '%s' "$DOWNLOADS_ACCESS" | jq -r '.password')

# Machine-readable listing
curl --fail-with-body -sS -u "$DOWNLOADS_USER:$DOWNLOADS_PASSWORD" -H 'Accept: application/json' "$DOWNLOADS_URL" | jq

# Browser-local streaming upload; response.browser_path is immediately usable
LOCAL_FILE='./report.pdf'
REMOTE_NAME=$(jq -rn --arg name "$(basename -- "$LOCAL_FILE")" '$name | @uri')
curl --fail-with-body -sS -X PUT -u "$DOWNLOADS_USER:$DOWNLOADS_PASSWORD" -H 'Content-Type: application/octet-stream' -H 'X-WebBrain-Upload-Target: browser' --upload-file "$LOCAL_FILE" "${DOWNLOADS_URL}${REMOTE_NAME}" | jq

# Full download and a byte-range download
curl --fail-with-body -sS -u "$DOWNLOADS_USER:$DOWNLOADS_PASSWORD" --output './report.pdf' "${DOWNLOADS_URL}${REMOTE_NAME}"
curl --fail-with-body -sS -u "$DOWNLOADS_USER:$DOWNLOADS_PASSWORD" -H 'Range: bytes=0-1023' --output './report.first-1KiB' "${DOWNLOADS_URL}${REMOTE_NAME}"

Upload response

A successful PUT returns the final collision-safe filename, byte size, SHA-256 digest, storage backend, and whether the file is already available at an absolute path inside the cloud browser.

{
  "name": "github-avatar-test.jpg",
  "size": 38564,
  "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
  "storage_backend": "browser_local",
  "browser_path": "/root/Downloads/github-avatar-test.jpg",
  "browser_ready": true
}
FieldTypeMeaning
namestringFinal filename after any collision suffix is applied.
sizenumberStored byte count.
sha256stringLowercase SHA-256 hex digest of the uploaded content.
storage_backendstringbrowser_local or shared_object.
browser_pathstring or nullAbsolute browser-visible filesystem path when locally materialized; otherwise null.
browser_readybooleantrue only when the browser can open browser_path immediately.

Incognito uploads are browser-local. For a ready, running normal browser, send X-WebBrain-Upload-Target: browser on the PUT to upload directly to that browser and receive its real absolute Downloads path with browser_ready: true. The request returns 409 Conflict while the browser is paused or not ready. Without the header, normal uploads use shared storage, remain available while paused, and return storage_backend: "shared_object", browser_path: null, and browser_ready: false. Existing path, url, etag, and idempotent fields may also be present for compatibility and shared-storage bookkeeping.

For normal browsers, shared Downloads are scoped to the user, remain online while Droplets are paused, and have a default 25 GiB fair-use allowance per user. Directory requests return the file tray by default and JSON when sent Accept: application/json. Files support GET, HEAD, one HTTP byte range, and raw streaming PUT uploads. Existing names receive a numbered suffix. Delete, rename, and folder creation are not available.

Chrome writes downloads to temporary Droplet staging. After Chrome reports completion, WebBrain uploads the file to shared storage and removes the local copy only after confirmation. Pause is refused while staging or sync work remains.

Client helpers

Node.js and PHP expose listDownloads, uploadDownloadsFile, and downloadDownloadsFile. Python exposes list_downloads, upload_downloads_file, and download_downloads_file. Set browserLocal: true in Node.js, browser_local=True in Python, or the PHP upload helper's final argument to true for a browser-local upload. All transfer file bodies as streams and protect existing local files unless overwrite is explicitly enabled.

Automation

Run a task

Runs are asynchronous by default and return 202 Accepted with a run_id. Poll the run endpoint, or set wait: true to wait until completion or until WebBrain needs user input.

AskRead the current page

Answers questions about an already-open tab without navigation or page-mutation tools.

FieldRequiredPurpose
taskOne ofThe natural-language browser task. Supply exactly one of task and workflow_id.
workflow_idOne ofAn owned saved workflow to replay.
parametersWorkflow onlyTransient string values keyed by declared parameter ID.
modeNoact (default) can interact with pages; ask is read-only on the current tab. Saved workflows always use Act.
waitNoWait for a terminal response instead of returning immediately.
timeout_msNoMaximum time for the blocking request path.
tab_idNoTarget a specific tab. Otherwise the visible active page is used.
output_schemaNoRequire a validated JSON result.
captureNovideo records the run; none is the default.
api_mutations_allowedNoOpt in to consequential HTTP API mutations for this run. Defaults to false.
POST/api/browser-sessions/:sessionId/runsStart a run.
GET/api/browser-sessions/:sessionId/scheduled-jobs?job_id=...Read status and outcomes for up to 100 explicit scheduled-job IDs.
GET/api/browser-sessions/:sessionId/runs/:runIdRead a run.
DELETE/api/browser-sessions/:sessionId/runs/:runIdDelete a finished run immediately.
POST/api/browser-sessions/:sessionId/runs/:runId/messagesAppend a turn after the run finishes.
POST/api/browser-sessions/:sessionId/runs/:runId/responsesAnswer its pending clarify_id.
POST/api/browser-sessions/:sessionId/runs/:runId/abortAbort a run.

Scheduled-job reads require one or more repeated job_id query parameters and return only those requested IDs. Ask mode does not expose navigation or page-mutation tools. To inspect a particular page in Ask mode, first open it with an Act run, then start an Ask run against the returned tab_id. Structured output_schema is supported in both modes. If the connected browser predates run-mode support, Ask returns 409 rather than silently running in Act.

The platform sanitizes cloud trace fields again before persistence. Finished run records are retained for seven days by default and can be deleted sooner through the run DELETE endpoint; active runs cannot be deleted.

Post a new task to /messages after a run is completed, failed, or aborted. WebBrain creates an immutable child run with parent_run_id and reuses the same tab, conversation, and mode unless a new mode is supplied. Append later turns to the newest child. Use /responses only for a paused needs_user_input run.

Repeat safely

Compile and replay saved workflows

Create a workflow from a completed successful cloud run with POST /api/workflows, or import the raw sanitized webbrain-workflow/1 JSON definition with POST /api/workflows/import. Portable files are limited to 1 MiB, never contain runtime parameter values, and receive a fresh cloud ID and timestamps.

  1. Complete a good runUse Act mode and verify that the run reached the intended result.
  2. Compile its traceCreate a workflow from the successful session and run IDs.
  3. Replay with parametersOpen a compatible start page and provide only the declared transient values.
POST/api/workflowsCompile and store an exact successful run trace.
POST/api/workflows/importValidate and store a portable workflow definition.
GET/api/workflows?limit=&offset=List workflow metadata.
GET/api/workflows/:workflowIdRead metadata and the sanitized definition.
GET/api/workflows/:workflowId/exportDownload the raw portable workflow JSON.
PATCH/api/workflows/:workflowIdRename a workflow.
DELETE/api/workflows/:workflowIdDelete the definition while retaining historical runs.

Before replay, open a page matching the workflow's start URL family in a compatible login/profile. Start it with workflow_id and parameters; output_schema is not supported for workflow runs in v1. Parameter values are validated before dispatch and are never stored or returned. A pre-upgrade runtime returns 409 for workflow operations but remains usable for ordinary tasks.

Typed results

Structured output

Use shorthand fields such as string, number, boolean, string[], and optional string?. The supported JSON Schema subset includes type, properties, required, items, enum, and additionalProperties.

Run state

Know when it is done

Keep polling while a run is active. Stop when it reaches a terminal state, or answer the exact clarification ID when WebBrain pauses for input.

runningneeds_user_inputcompletedfailedabortingaborted
StatusTerminal?What your code should do
runningNoContinue polling the run.
needs_user_inputNoRead pending_input and post its clarify_id with the user's answer.
completedYesRead result, summary, and final_url.
failedYesInspect error; correct the task, page state, or browser state before retrying.
abortingNoWait until the abort finishes.
abortedYesStart a new run if more work is needed.

A terminal response includes result, summary, final_url, and any failure detail in error.

Recovery

Errors tell you what to fix

API failures return JSON with an error message. State conflicts may include extra runtime detail so your code can decide whether to wait, reconnect, or ask the user to intervene.

400
Invalid requestFix a missing, conflicting, or malformed field.
401
Authentication failedSend a valid Bearer key owned by the account.
402
Credit exhaustedAdd credit before provisioning or using a billed model route.
404
Resource not foundCheck the ID and confirm it belongs to this key.
409
State conflictWait for readiness or finish the active lifecycle or run operation.
503
Capability unavailableA required runtime or storage service is not configured or connected.
Retry deliberately: retry temporary readiness and connection conflicts with bounded backoff. Do not blindly retry validation, authentication, ownership, or credit failures.

Open Agent Skill

Give your agent a cloud browser

The website publishes a portable webbrain-cloud skill for Codex, ChatGPT, OpenClaw, Claude Code, and Claude chat or Cowork. It teaches the agent session selection, readiness polling, run continuations, clarification handling, file transfer, cleanup, and the security boundaries around browser actions.

Choose macOS/Linux or Windows PowerShell below and install the skill, then provide WEBBRAIN_API_KEY through the agent runtime's environment or secret manager. Do not put the key inside SKILL.md, its ZIP, a prompt, or a tracked file. The runtime also needs Node.js 18+ and outbound HTTPS access to webbrain.cloud.

git clone --depth 1 https://github.com/esokullu/webbrain-platform.git
mkdir -p "$HOME/.agents/skills"
cp -R webbrain-platform/.agents/skills/webbrain-cloud "$HOME/.agents/skills/"

Codex and OpenClaw discover the checked-in .agents/skills location, while Claude Code uses the checked-in .claude/skills loader. ChatGPT, Claude chat, and Cowork accept the packaged ZIP through their Skills UI; code execution and network access must be enabled.

No dependencies

Use your language

The repository includes small clients with the same core operations: session creation, pause and resume, readiness, runs, follow-up turns, polling, aborting, structured output, noVNC links, and streaming private Downloads transfers.