Reference

API reference

The full REST surface at https://sessions.browserview.io. Lifecycle endpoints take your API key; per-session traffic takes a scoped session token.

Authentication

Send your API key on every lifecycle request, either as a bearer token or an x-api-key header:

Authorization: Bearer bv_live_...# orx-api-key: bv_live_...

Keys are minted in the console and can be revoked there at any time; revocation takes effect within about a minute. Your key sees only your own sessions.

Endpoints

MethodPathPurpose
POST/sessionsCreate a session
GET/sessionsList your sessions
GET/sessions/{id}Inspect one session (returns fresh URLs and tokens)
DELETE/sessions/{id}Destroy a session
POST/sessions/{id}/tokensMint an extra scoped token
GET/sessions/{id}/replayReplay manifest for a recorded session (works after destruction)

Create a session

POST /sessions
{  "start_url": "https://example.com",  // default "about:blank"  "width": 1280,                       // 320–3840, default 1280  "height": 800,                       // 240–2160, default 800  "wait": true,                        // block until the browser is ready  "record": true                       // capture a session replay (default false)}

Returns 201 with the session object. The viewer_url, watch_url, and cdp_url fields are paths relative to the API host. With "wait": true (the default) the call returns once the browser answers on DevTools — typically about five seconds.

The session object

{  "id": "3f9c62d81b4a",  "status": "running",          // container state  "health": "healthy",          // healthy | starting | unhealthy  "start_url": "https://example.com",  "width": 1280,  "height": 800,  "created_at": "2026-07-29T17:04:05Z",  "record": false,              // whether a replay is being captured  "mem_limit_bytes": 2147483648,  "viewer_url": "/sessions/3f9c62d81b4a/viewer?token=...",  // control scope  "watch_url":  "/sessions/3f9c62d81b4a/viewer?token=...",  // view scope  "cdp_url":    "/sessions/3f9c62d81b4a/cdp",  "cdp_token":  "...",  "token_ttl_seconds": 3600}

GET /sessions (the list endpoint) returns a bare JSON array and omits the URL and token fields; fetch a single session to get fresh ones. GET /sessions/{id} additionally reports browser health: restarts (times the in-session browser restarted, or null when the status probe is unreachable) and degraded (true once it has restarted). DELETE /sessions/{id} returns 204 with no body.

Mint a token

POST /sessions/{id}/tokens
{  "scope": "view",        // view | control | cdp  "ttl_seconds": 900      // up to 7 days} // 200 → { "token": "...", "scope": "view", "ttl_seconds": 900 }

Fetch a replay

GET /sessions/{id}/replay
// while the session runs        → 200 { "status": "recording", ... }// just ended, still finalizing  → 404 — not an error; retry for a few seconds// once finalized (typically <30s) → 200 with the full manifest:{  "status": "ready",  "video":  { "url": "...", "start_time_ms": ..., "duration_ms": ... },  "pages":  [ { "page_id": "p_000", "url": "...",                "start_time_ms": ..., "end_time_ms": ... } ],  "events": { "actions": {...}, "console": {...},              "network": {...}, "errors": {...} },  "urls_expire_at_ms": ...}

Only sessions created with record: true have replays. The SDKs' waitForReplay / wait_for_replay helpers poll through the recording and finalizing states for you. See the session replay guide for stream formats and timeline math.

Token scopes

ScopeGrants
viewWatch the live stream. Input is stripped server-side — spectators physically cannot click or type.
controlWatch plus full mouse and keyboard.
cdpChrome DevTools Protocol access for Playwright, Puppeteer, or raw CDP clients.

Tokens are signed, scoped to one session, and expire (one hour by default). Pass them as ?token= or the x-session-token header.

Connecting over CDP

The API rewrites Chromium's discovery JSON so webSocketDebuggerUrl points back through the proxy with your token attached — Playwright and Puppeteer work with no special configuration beyond the header:

// Playwrightconst browser = await chromium.connectOverCDP(cdpUrl, {  headers: { "x-session-token": cdpToken },}); // Puppeteerconst browser = await puppeteer.connect({  browserURL: cdpUrl + "?token=" + cdpToken,});

Errors and rate limits

Errors are JSON: {"detail": "..."}.

StatusMeaning
401Missing or invalid API key.
403Valid token, wrong scope — or a plan limit: included browser-hours exhausted on the free tier, plan concurrency reached, or a failed payment. Upgrade or manage billing in the console.
404Session not found (or not yours).
429Rate limit or capacity: concurrent-session limit reached, or the fleet is momentarily full. Honor the Retry-After header.
503Authentication service briefly unavailable — retry.

Liveness is exposed at GET https://sessions.browserview.io/healthz.