Docs
Dashboard
API reference / SessionsBeta

Create a session

Claims a warm machine with a browser and/or a shell. Limited to 120 per minute per project, and to the plan's concurrent sessions (429 concurrency_limit). 503 no_capacity when no machine is free in time. browser (default true) and shell (default false) choose the kind: browser only, shell only ({browser: false, shell: true}) or both. Without a browser connectUrl and liveUrl are null; without a shell terminalUrl is.

POST/v1/sessions

Request

Method and pathPOST/v1/sessions
Base URLhttps://api.boxline.dev
AuthenticationYour API key in the x-api-key header (or Authorization: Bearer). The examples read it from BOXLINE_API_KEY.
Safe retriesSend an Idempotency-Key header to retry without creating anything twice. See Idempotency keys.
Rate limitYes. See Rate limits for the numbers and headers.

Headers

NameTypeDefaultAllowed valuesDescription
Idempotency-Keystring––Makes a retry safe: the same key and body within 24 hours returns the first response (with Idempotent-Replayed: true) instead of creating something twice. 1 to 255 printable ASCII characters without spaces, e.g. a UUID. Keys belong to the project (a new API key is replayed only to its caller). At most 300 new keys per minute per project (429). 1 to 255 characters.

Body

JSON with content-type: application/json. Optional: you can leave the body out.

NameTypeDefaultAllowed valuesDescription
browserboolean | object––true or omitted: a browser with the defaults; false: none; an object: a browser with these settings.
browser.modestringstandardstandard, realisticrealistic puts the clock and language on the proxy's country. It never changes what the browser reports about itself.
browser.localestring––BCP 47, e.g. de-DE. Wins over the mode.
browser.timezonestring––IANA, e.g. Europe/Berlin. Wins over the mode.
shellbooleanfalse–A bash shell with Python, Node, ffmpeg and sudo, sharing /workspace.
timeoutinteger300–Seconds, up to the plan's maxTimeoutSeconds (402 plan_limit). At least 60.
idleTimeoutinteger | 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.
keepAlivebooleanfalse–Keep a browser-only session after its last client disconnects.
viewportobject––
viewport.widthrequiredinteger––From 200 to 3840.
viewport.heightrequiredinteger––From 200 to 2160.
userMetadataobject––
profileobject––
profile.idrequiredstring––
profile.persistbooleanfalse–Save the browser's logins back into the profile at the end.
recordSessionbooleantrue–
setupstring[]––Shell commands run in order when the session starts, and again after a resume (needs shell). Up to 20 items.
proxyboolean | 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.typerequiredstring–residential, datacenter, custom
proxy.countrystring––Two-letter country code (residential and datacenter).
proxy.statestring––Residential, US states, e.g. us_california (implies US).
proxy.citystring––Residential, e.g. los_angeles (needs country).
proxy.ipstring–sticky, rotatingDefault sticky for sessions and crawls, rotating for fetch, screenshot, pdf and extract.
proxy.scopestringbrowserbrowser, allall also routes the session's shell.
proxy.serverstring––custom: your proxy, http://host:port or https://host:port, on a public address.
proxy.usernamestring––
proxy.passwordstring––Stored encrypted; never returned.
proxy[].domainPatternstring––Up to 256 characters.
captchastring–ask, ignore, solveWhat 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.
blockAdsbooleanfalse–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.
cookieBannersstringrejectreject, offreject: 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.
extensionsstring[]––Uploaded extensions (POST /v1/extensions) to load into the browser; needs the plan feature extensions. Up to 10 items.
envobject––Variables for the session's shell (needs shell): new terminals, exec, scripts and setup commands get them, and they are set again on every new machine (resume, recovery). Names like the shell's ([A-Za-z_][A-Za-z0-9_]*, not PATH, HOME or BOXLINE_*), 64 KB together. Kept sealed; the session shows the names only.
credentialsstring[]––Credentials exported into the shell, one variable per field: a secret as $NAME, a password as $NAME_USERNAME and $NAME_PASSWORD (and boxline-otp NAME prints its 2FA code). Needs shell; the credential needs scope "shell" or "all", or shell true (else 400 credential_not_for_shell). Kept in the machine's memory only (never a file in /workspace), set again on every new machine, and hidden in exec, script and terminal output. Up to 50 items.

More examples:

A shell only
{"browser":false,"shell":true}
A browser session for 10 minutes
{"timeout":600,"viewport":{"width":1280,"height":720}}
A browser and a shell, with packages installed at start
{  "shell": true,  "setup": [    "pip install yt-dlp"  ],  "userMetadata": {    "job": "nightly"  }}
A residential proxy in Germany, with the clock and language to match
{  "proxy": {    "type": "residential",    "country": "DE"  },  "browser": {    "mode": "realistic"  }}
No ads or trackers, cookie banners rejected, one uploaded extension
{  "blockAds": true,  "cookieBanners": "reject",  "extensions": [    "ext_Q2x9L0aPz7NmK3Jb"  ]}
curl -X POST "https://api.boxline.dev/v1/sessions" \  -H "x-api-key: $BOXLINE_API_KEY" \  -H "Idempotency-Key: $(uuidgen)"

Responses

201 Created

The running session.

Headers

  • RateLimit-Limit: Requests allowed in the current window of this route's limit. (Rate limits)
  • RateLimit-Remaining: Requests left in the current window. (Rate limits)
  • RateLimit-Reset: Seconds until the window starts again. (Rate limits)
  • Idempotent-Replayed: true when this is the kept response of an earlier request with the same Idempotency-Key. (Idempotency keys)

Fields

NameTypeDefaultAllowed valuesDescription
idstring––
statusstring–RUNNING, STOPPED, DELETED, ERRORRUNNING; STOPPED (saved, no machine, free); DELETED (ended for good, its data gone); ERROR (only a session that never started).
projectIdstring––
regionstring––
browserboolean––
shellboolean––
keepAliveboolean––
timeoutinteger––Seconds.
idleTimeoutinteger | null––Seconds without activity after which it stops (stopReason idle); null: off.
createdAtstring––Format: date-time.
startedAtstring | null––Format: date-time.
expiresAtstring––Format: date-time.
stoppedAtstring | null––When it stopped (null while it runs; cleared by a resume). Format: date-time.
stopReasonstring | null––requested, timeout, idle, no_clients, agent_run, task, machine_lost, api_restart, account_recovered, suspended, spend_limit or out_of_credit.
deletesAtstring | null––When a stopped session is deleted automatically: stoppedAt plus the plan's retentionDays, fixed when it stops. Format: date-time.
deletedAtstring | null––Format: date-time.
deleteReasonstring | null–requested, retention, null
connectUrlstring | null––CDP WebSocket for Playwright/Puppeteer (null without a browser or unless the session is running). Treat it like a password.
liveUrlstring | null––The live view page (null without a browser
terminalUrlstring | null––The terminal WebSocket (null without a shell). Treat it like a password.
proxynull | object | object[]––The session's proxy as given, without passwords.
proxy.typestring–residential, datacenter, custom
proxy.countrystring––Two-letter country code (residential and datacenter).
proxy.statestring––Residential, US states, e.g. us_california (implies US).
proxy.citystring––Residential, e.g. los_angeles (needs country).
proxy.ipstring–sticky, rotatingDefault sticky for sessions and crawls, rotating for fetch, screenshot, pdf and extract.
proxy.scopestringbrowserbrowser, allall also routes the session's shell.
proxy.serverstring––custom: your proxy, http://host:port or https://host:port, on a public address.
proxy.usernamestring––
proxy[].domainPatternstring––Up to 256 characters.
browserSettingsobject––What is in force (locale and timezone null = the browser's own default).
browserSettings.modestring–standard, realistic
browserSettings.localestring | null––
browserSettings.timezonestring | null––
viewportobject | null––
viewport.widthinteger––From 200 to 3840.
viewport.heightinteger––From 200 to 2160.
trajectoriesEligibleboolean––
captchastring–ask, ignore, solveWhat 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.
attentionobject | null––A CAPTCHA waiting (or being solved), else null.
attention.typestring–captcha
attention.kindstring–recaptcha, hcaptcha, turnstile, cloudflare, datadome, arkose, human
attention.urlstring––
attention.tabIdstring––
attention.sincestring––Format: date-time.
attention.statestring–solving, waiting
attention.reasonstring––
blockAdsboolean––
blockedRequestsinteger––Requests to ad and tracker sites refused so far (collected about every 30 s).
cookieBannersstring–reject, off"off" for sessions without a browser, and for sessions created before the option existed.
extensionsstring[]––The extension ids the session started with.
workspacePathstring––
profileIdstring | null––
profilePersistboolean––Whether the session saves its sign-ins back to profileId when it ends (persist:true, or attached with fromSession). false without a profile.
userMetadataobject––
checkpointAtstring | null––Format: date-time.
recoveriesinteger––Times the session was brought back on a new machine after its machine stopped.
errorstring | null––
recordSessionboolean––
setupstring[]––
setupStatusstring–none, running, done, failed
setupErrorstring | null––
envstring[]––Names of the session's env variables (values are never returned).
credentialsstring[]––Names of the credentials its shell exports (a profile's linked one included).
hasRecordingboolean––
usageobject––
usage.secondsnumber––
usage.costUsdnumber––
Response 201
{  "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.

StatusCodesWhen
400 Bad Requestinvalid_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_tokenThe request is not valid.
401 UnauthorizedunauthorizedMissing or invalid API key.
402 Payment Requiredfeature_not_in_plan, spend_limit, out_of_credit, plan_limit, spend_limit, out_of_credit, organization, project, plan, creditThe 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.
403 Forbiddenproject_suspended, organization_suspended, role_forbidden, forbidden, extension_denied, cross_site_request, console_login_required, impersonating, invite_email_mismatch, email_unconfirmedNot allowed.
404 Not Foundnot_found, invite_not_found, provider_unavailableNo such thing in this project (or organization), or no such route.
409 Conflictsession_not_running, shell_disabled, browser_disabled, nothing_saved, not_resumable, invalid_state, conflict, email_taken, identity_in_use, provider_already_linked, last_sign_in_method, not_impersonating, machine_too_old, too_many_credential_values, limit_reached, terms_version_mismatch, no_project, last_owner, organization_not_empty, project_has_sessions, already_member, invite_pending, idempotency_in_progressThe current state does not allow it, or a request with this Idempotency-Key is still being answered.
422 Unprocessable Contentidempotency_mismatchThis Idempotency-Key was already used for a different request.
429 Too Many Requestsrate_limited, concurrency_limitToo many requests, or the organization's concurrent sessions (its plan's) or the project's concurrencyCap are in use.
503 Service Unavailableno_capacity, proxy_unavailable, provider_unavailable, search_unavailable, webhooks_unavailable, mail_unavailable, browser_unreachableNo 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 body
{  "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.