Update a session
The one call that changes a running session, with the field names and shapes of Create a session. Checks first, then the changes, so a bad value leaves the session as it was. A new proxy applies at once (the browser's open connections are closed); null removes it. Browser settings apply to every tab within a second or two. blockAds and cookieBanners apply at once. timeout changes its length, rotateProxy gives a new proxy IP, rotateUrls makes new signed URLs. What is fixed when the session starts (browser and shell on or off, viewport, profile, recordSession, setup, extensions, env, credentials) is 400 not_updatable. A stopped session takes the changes too; they apply when it resumes. 409 session_not_running for a deleted session.
/v1/sessions/{id}Request
| Method and path | PATCH/v1/sessions/{id} |
|---|---|
| Base URL | https://api.boxline.dev |
| Authentication | Your API key in the x-api-key header (or Authorization: Bearer). The examples read it from BOXLINE_API_KEY. |
Path parameters
| Name | Type | Default | Allowed values | Description |
|---|---|---|---|---|
idrequired | string | – | – |
Body
JSON with content-type: application/json. Required.
| Name | Type | Default | Allowed values | Description |
|---|---|---|---|---|
keepAlive | boolean | – | – | Keep the session running when its last client leaves (as on create); false lets it stop when the last client has gone. |
timeout | integer | – | – | The session's length in seconds, counted from its last start (a resume restarts it), as on create; expiresAt moves to match. At least 60 s from now, at most the plan's maxTimeoutSeconds (402 plan_limit). At least 60. |
idleTimeout | integer | null | – | – | Opt-in (default off): the session stops (stopReason idle) after this many seconds without activity: 30 to its timeout. Activity: CDP commands through the gateway, live-view input, terminal keys, exec, files calls, actions and steps, scripts, agent steps and messages; an agent run working in the session (or one that can still be resumed) counts the whole time. Checked every few seconds. null switches it off (PATCH). At least 30. |
userMetadata | object | – | – | Your own JSON (at most 16 KB), replaced as a whole; sent with the session's webhooks and shown on it. |
proxy | boolean | null | object | object[] | – | – | true = a residential US proxy; an object = one proxy; a list = rules by site (at most 10); null or false = none. |
proxy.typerequired | string | – | residential, datacenter, custom | |
proxy.country | string | – | – | Two-letter country code (residential and datacenter). |
proxy.state | string | – | – | Residential, US states, e.g. us_california (implies US). |
proxy.city | string | – | – | Residential, e.g. los_angeles (needs country). |
proxy.ip | string | – | sticky, rotating | Default sticky for sessions and crawls, rotating for fetch, screenshot, pdf and extract. |
proxy.scope | string | browser | browser, all | all also routes the session's shell. |
proxy.server | string | – | – | custom: your proxy, http://host:port or https://host:port, on a public address. |
proxy.username | string | – | – | |
proxy.password | string | – | – | Stored encrypted; never returned. |
proxy[].domainPattern | string | – | – | Up to 256 characters. |
captcha | string | – | ask, ignore, solve | What happens when a CAPTCHA waits for a person. ask (default): agent runs and steps pause and hand over. ignore: they carry on. solve (opt-in, paid plans): the platform tries to solve it first. |
browser | object | – | – | The browser's settings (never on or off). |
browser.mode | string | – | standard, realistic | |
browser.locale | string | – | – | |
browser.timezone | string | – | – | |
blockAds | boolean | false | – | Refuse requests to ad and tracker sites inside the machine (its local proxy), with or without a session proxy. Blocked requests are counted in blockedRequests and reported in lifecycle events. |
cookieBanners | string | reject | reject, off | reject: answer consent banners of the common platforms with "Reject all" or "Necessary only" (never accept), else hide them, in every tab and frame. Each answer is a lifecycle event. |
rotateProxy | boolean | – | – | A new proxy IP now; the browser's open connections are closed so they reconnect on it. 400 without a proxy. |
rotateUrls | boolean | – | – | New signed connectUrl, liveUrl and terminalUrl; every earlier one stops working and connections made with them are closed. The answer carries the new ones. |
curl -X PATCH "https://api.boxline.dev/v1/sessions/$SESSION_ID" \ -H "x-api-key: $BOXLINE_API_KEY" \ -H "content-type: application/json" \ -d '{"timeout": 3600, "keepAlive": true}'import { Boxline } from "@boxline/sdk";const bx = new Boxline(); // reads BOXLINE_API_KEY and BOXLINE_API_URLconst session = await bx.sessions.update("SESSION_ID", { timeout: 3600, keepAlive: true });console.log(session.data.expiresAt); // moved to match timeoutfrom boxline import Boxlinebx = Boxline() # reads BOXLINE_API_KEY and BOXLINE_API_URLsession = bx.sessions.update("SESSION_ID", timeout=3600, keep_alive=True)print(session.expires_at) # moved to match timeoutResponses
200 OK
The session.
Fields
| Name | Type | Default | Allowed values | Description |
|---|---|---|---|---|
id | string | – | – | |
status | string | – | RUNNING, STOPPED, DELETED, ERROR | RUNNING; STOPPED (saved, no machine, free); DELETED (ended for good, its data gone); ERROR (only a session that never started). |
projectId | string | – | – | |
region | string | – | – | |
browser | boolean | – | – | |
shell | boolean | – | – | |
keepAlive | boolean | – | – | |
timeout | integer | – | – | Seconds. |
idleTimeout | integer | null | – | – | Seconds without activity after which it stops (stopReason idle); null: off. |
createdAt | string | – | – | Format: date-time. |
startedAt | string | null | – | – | Format: date-time. |
expiresAt | string | – | – | Format: date-time. |
stoppedAt | string | null | – | – | When it stopped (null while it runs; cleared by a resume). Format: date-time. |
stopReason | string | null | – | – | requested, timeout, idle, no_clients, agent_run, task, machine_lost, api_restart, account_recovered, suspended, spend_limit or out_of_credit. |
deletesAt | string | null | – | – | When a stopped session is deleted automatically: stoppedAt plus the plan's retentionDays, fixed when it stops. Format: date-time. |
deletedAt | string | null | – | – | Format: date-time. |
deleteReason | string | null | – | requested, retention, null | |
connectUrl | string | null | – | – | CDP WebSocket for Playwright/Puppeteer (null without a browser or unless the session is running). Treat it like a password. |
liveUrl | string | null | – | – | The live view page (null without a browser |
terminalUrl | string | null | – | – | The terminal WebSocket (null without a shell). Treat it like a password. |
proxy | null | object | object[] | – | – | The session's proxy as given, without passwords. |
proxy.type | string | – | residential, datacenter, custom | |
proxy.country | string | – | – | Two-letter country code (residential and datacenter). |
proxy.state | string | – | – | Residential, US states, e.g. us_california (implies US). |
proxy.city | string | – | – | Residential, e.g. los_angeles (needs country). |
proxy.ip | string | – | sticky, rotating | Default sticky for sessions and crawls, rotating for fetch, screenshot, pdf and extract. |
proxy.scope | string | browser | browser, all | all also routes the session's shell. |
proxy.server | string | – | – | custom: your proxy, http://host:port or https://host:port, on a public address. |
proxy.username | string | – | – | |
proxy[].domainPattern | string | – | – | Up to 256 characters. |
browserSettings | object | – | – | What is in force (locale and timezone null = the browser's own default). |
browserSettings.mode | string | – | standard, realistic | |
browserSettings.locale | string | null | – | – | |
browserSettings.timezone | string | null | – | – | |
viewport | object | null | – | – | |
viewport.width | integer | – | – | From 200 to 3840. |
viewport.height | integer | – | – | From 200 to 2160. |
trajectoriesEligible | boolean | – | – | |
captcha | string | – | ask, ignore, solve | What happens when a CAPTCHA waits for a person. ask (default): agent runs and steps pause and hand over. ignore: they carry on. solve (opt-in, paid plans): the platform tries to solve it first. |
attention | object | null | – | – | A CAPTCHA waiting (or being solved), else null. |
attention.type | string | – | captcha | |
attention.kind | string | – | recaptcha, hcaptcha, turnstile, cloudflare, datadome, arkose, human | |
attention.url | string | – | – | |
attention.tabId | string | – | – | |
attention.since | string | – | – | Format: date-time. |
attention.state | string | – | solving, waiting | |
attention.reason | string | – | – | |
blockAds | boolean | – | – | |
blockedRequests | integer | – | – | Requests to ad and tracker sites refused so far (collected about every 30 s). |
cookieBanners | string | – | reject, off | "off" for sessions without a browser, and for sessions created before the option existed. |
extensions | string[] | – | – | The extension ids the session started with. |
workspacePath | string | – | – | |
profileId | string | null | – | – | |
profilePersist | boolean | – | – | Whether the session saves its sign-ins back to profileId when it ends (persist:true, or attached with fromSession). false without a profile. |
userMetadata | object | – | – | |
checkpointAt | string | null | – | – | Format: date-time. |
recoveries | integer | – | – | Times the session was brought back on a new machine after its machine stopped. |
error | string | null | – | – | |
recordSession | boolean | – | – | |
setup | string[] | – | – | |
setupStatus | string | – | none, running, done, failed | |
setupError | string | null | – | – | |
env | string[] | – | – | Names of the session's env variables (values are never returned). |
credentials | string[] | – | – | Names of the credentials its shell exports (a profile's linked one included). |
hasRecording | boolean | – | – | |
usage | object | – | – | |
usage.seconds | number | – | – | |
usage.costUsd | number | – | – |
{ "id": "6c1f3c9e-1d2a-4f67-9b0e-1b2c3d4e5f60", "status": "RUNNING", "projectId": "prj_Hk2Lq8Zx0Vb5Nm1C", "region": "us-east-1", "browser": true, "shell": false, "keepAlive": false, "timeout": 300, "createdAt": "2026-09-29T10:00:00.000Z", "startedAt": "2026-09-29T10:00:00.000Z", "expiresAt": "2026-09-29T10:05:00.000Z", "stoppedAt": null, "stopReason": null, "deletesAt": null, "deletedAt": null, "deleteReason": null, "connectUrl": "wss://connect.boxline.dev/v1/connect?sessionId=6c1f3c9e-1d2a-4f67-9b0e-1b2c3d4e5f60&token=…", "liveUrl": "https://api.boxline.dev/live/6c1f3c9e-1d2a-4f67-9b0e-1b2c3d4e5f60?token=…", "terminalUrl": null, "proxy": null, "browserSettings": { "mode": "standard", "locale": null, "timezone": null }, "viewport": { "width": 1280, "height": 720 }, "trajectoriesEligible": false, "captcha": "ask", "attention": null, "blockAds": false, "blockedRequests": 0, "cookieBanners": "reject", "extensions": [], "workspacePath": "/workspace", "profileId": null, "profilePersist": false, "userMetadata": {}, "checkpointAt": null, "recoveries": 0, "error": null, "recordSession": true, "setup": [], "setupStatus": "none", "setupError": null, "env": [], "credentials": [], "hasRecording": false, "usage": { "seconds": 12.3, "costUsd": 0.00015 }}Errors
Errors have a matching HTTP status and the same body. code is stable, so check it in your code; message is for people. See Errors and request ids.
| Status | Codes | When |
|---|---|---|
| 400 Bad Request | invalid_request, invalid_json, invalid_cursor, invalid_idempotency_key, invalid_extension, variables_with_extensions, terms_not_accepted, invalid_reset_token, invalid_confirmation_code, wrong_password, no_password, invalid_next, invalid_oauth_token | The request is not valid. |
| 401 Unauthorized | unauthorized | Missing or invalid API key. |
| 402 Payment Required | feature_not_in_plan, spend_limit, out_of_credit, plan_limit, spend_limit, out_of_credit, organization, project, plan, credit | The plan does not include this, a monthly allowance or spending limit is used up, the organization has no credit left, or the plan allows no more of this. spend_limit and out_of_credit carry error.details.limit: organization, project, plan or credit. |
| 404 Not Found | not_found, invite_not_found, provider_unavailable | No such thing in this project (or organization), or no such route. |
| 503 Service Unavailable | no_capacity, proxy_unavailable, provider_unavailable, search_unavailable, webhooks_unavailable, mail_unavailable, browser_unreachable | No machine free in time, proxies not set up, the model provider is not configured or has no key, or web search is not set up or its provider is not answering, or webhook delivery is not set up, or an email cannot be sent, or the session's browser did not answer in time. |
{ "error": { "code": "not_found", "message": "session not found", "requestId": "req_4fJx0aQm2Lk9Pz7N" }}Learn more
These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.