Skip to main content
Theo Browser gives your app a managed headless Chromium session that an LLM agent can drive through natural language tools (browser_navigate, browser_act, browser_extract, browser_observe, browser_screenshot), and surfaces the session through an iframe-embeddable live view so your users can watch (or take over) in real time. All four endpoints below are scoped to the caller’s API key and gated behind the connectors scope. Sessions are hard-capped at 20 minutes by default and auto-closed on idle timeout (configurable via THEO_BROWSER_SESSION_MAX_SECONDS / THEO_BROWSER_SESSION_IDLE_SECONDS).

Endpoints

Create a session

Request Body

url
string
Optional starting URL. The session will navigate immediately after launch so the first live view URL already targets the real page (avoids the about:blank target-bind issue).
keep_alive
boolean
default:"false"
Keep the session alive across agent disconnects. Required if you want to reconnect Stagehand later.
proxies
boolean
default:"false"
Route traffic through Theo’s residential proxy pool. Billed higher per MB.
region
string
default:"us-west-2"
Datacenter region: us-west-2 · us-east-1 · eu-central-1 · ap-southeast-1.

Response (201)

embed_url is the zero-config path. Drop it directly into an <iframe src="..."> on your own product and you get the Theo-branded browser window (URL bar, live indicator, reconnect UI) with no SDK wiring. The token is short-lived — call GET /:id from your backend to mint a fresh one.

Refresh the live view URL

BrowserBase’s debugger URL is pinned to a specific CDP page target. When the agent navigates, clicks something that opens a new tab, or the page destroys its target, the embedded WebSocket disconnects. Theo automatically force-refreshes after every agent tool call — but your own UI should also refresh on demand:
Why live_view_version matters. When the iframe emits a browserbase-disconnected postMessage, refetch with ?force=1. The upstream provider can return the same URL string while silently swapping the underlying page target. Use live_view_version (not URL equality) to decide when to rekey the iframe.

Response

List active sessions

Returns { sessions: BrowserSessionSnapshot[] } — same per-session shape as GET /:id.

Inspect a session

Every call mints a fresh embed_url (1 h TTL) so long-running dashboards can re-issue iframes without spinning up a new session.

End a session

Response

Always end sessions explicitly. Idle / max-duration sweepers will close them eventually, but you are billed for the elapsed wall-clock time until then.

Errors