Session lifecycle
A session lives until you end it, its lifetime cap fires, it sits idle, or — if you ask — its last client disconnects. Every knob is set at create and can be adjusted while it runs.
Create-time knobs
POST /sessions
{ "timeout_seconds": 3600, // hard lifetime cap; clamped to the plan (15 min Free, 4 h paid). Alias of max_lifetime_seconds "idle_timeout_seconds": 300, // end after N seconds with no CDP/viewer/agent activity; 0 disables (lifetime still applies) "keep_alive": true, // default true. false = end 30 s after the last client disconnects (once one has connected) "region": "us-east-1" // placement; currently the only value (anything else → 400)}- Idle time is reset by CDP traffic, viewer input, and hosted-agent steps. The server default idle timeout is 15 minutes.
keep_alive: falseis the cheapest way to run one-shot jobs: connect, work, disconnect, and the browser is gone 30 seconds later without a DELETE.
What the session object tells you
{ "status": "running", // pending | running | completed | timed_out | error "end_reason": null, // once ended: api | lifetime | idle | dead | unhealthy | sweep | released | client_disconnect "created_at": "2026-08-29T20:00:00Z", "expires_at": "2026-08-29T21:00:00Z", // created_at + lifetime "idle_timeout_seconds": 300, "keep_alive": true, "region": "us-east-1", "usage": { "duration_seconds": 412, "proxy_bytes": 1048576, "captcha_solves": 0 }}| status | Meaning |
|---|---|
pending | Container starting; the browser has not answered on DevTools yet. |
running | Ready — connect over CDP or open the viewer. |
completed | Ended normally (DELETE, release, or client disconnect). |
timed_out | The lifetime cap or the idle timeout fired. |
error | The browser died, became unhealthy, or was swept, and was torn down. |
The older health and low-level state fields remain on the object; status is the one to branch on.
Extend or shorten a running session
PATCH /sessions/{id}
{ "timeout_seconds": 7200, "idle_timeout_seconds": 0, "keep_alive": true }// 200 → the updated session object (expires_at moves). Values are clamped to the plan caps.Release vs destroy
POST /sessions/{id}/release // 202, idempotent — graceful end, end_reason "released"DELETE /sessions/{id} // 204 — immediate teardown, end_reason "api"Both finalize replays, archive the persistent context, and fire the session.ended webhook. Release lets in-flight work (a pending download, the recorder's last segment) finish first and is safe to call more than once.
Events
Lifecycle transitions appear on the session event stream as session.released alongside the existing events, and every ended session carries its final usage into the completion webhook and the console's History view.