stealthDOCS
Browsers

Browsers

Create an isolated Camoufox instance, wait for it to run, configure its locale, viewport, lifetime and navigation policy, follow its events, and stop it.

Create

POST /v1/browsers → 202 with the Browser resource and a Location header. Poll GET /v1/browsers/{id} until status is running before sending commands; the SDKs' ready() does that.

POST /v1/browsers
{  "profile_id": "pf_…",  "credential_ids": ["cred_…"],  "settings": {    "locale": "en-US",    "timezone": "Europe/Berlin",    "viewport": { "width": 1280, "height": 800 },    "idle_timeout_ms": 600000,    "timeout_ms": 1800000,    "record_video": false,    "network": { "mode": "direct" },    "navigation": { "allow": ["example.com", "*.example.com"], "block": [], "block_raw_ip": true }  }}

profile_id starts the browser with a saved Profile; credential_ids (up to 16 project login credentials) lets it type a saved password as {{secret:<name>}} without your code ever holding the value — see Observe and act.

SettingMeaning
locale, timezoneThe browser's locale and time zone in direct mode; a proxied browser takes both from the exit's GeoIP instead
viewportWidth and height
idle_timeout_msStop after this long without a command; default 600000
timeout_msTotal lifetime; default 1800000. Both lifetimes range 1000–3600000
record_videoRecord the page as VP8 WebM — see Downloads and recordings
networkdirect, managed or custom — see Network
navigationallow / block host patterns and block_raw_ip; a refused navigation is navigation_blocked (409)
profile_idStart with a Profile's saved state — see Profiles

Headless operation and the engine are fixed; launch options of the local CLI are not accepted. The launch itself has a 60 s budget; a launch failure appears on the resource (browser_launch_failed) after the 202.

Idempotency-Key on create returns the same instance for the same settings and profile; different settings answer conflict.

Status

StatusMeaning
startingLaunching
runningReady for commands
stoppingA stop is in progress
stoppedReleased; stop_reason says why (requested, idle, lifetime, credential_revoked, …)
failedLaunch or Worker failure; error carries the code
cleanup_failedRelease could not be verified; the instance still occupies capacity until an operator resolves it

resources_released says whether the instance still counts against capacity. GET /v1/browsers lists the project's instances; GET /v1/browsers/{id}/control says whether an Agent run owns the browser (run_id) — manual actions answer conflict while one does.

Stop

POST /v1/browsers/{id}/stop with {} → the final resource: 200 after a verified release, 502 with the resource when cleanup could not be verified. A stop also saves the browser's Profile when it has one.

Events

GET /v1/browsers/{id}/events?after=0 → { "data": [Event], "next_cursor": 6 }; &stream=1 streams server-sent events until an end event once the browser is stopped, failed or cleanup_failed. Types: browser.starting, browser.running, browser.stopping, browser.stopped, browser.failed, browser.cleanup_failed, browser.navigated, browser.snapshot, browser.action, browser.network_checked, browser.secrets_set, browser.files_staged. At most 256 events per browser; an expired cursor answers events_expired.

Capacity

Capacity is per deployment, shared by every project. A create that finds every slot taken waits its turn — in arrival order, up to the deployment's admission wait (30 seconds by default) — and starts as soon as a slot frees; capacity_exceeded (429) comes only when the wait runs out or the line is full. The request is held open while it waits, so give the create call that much timeout; meanwhile GET /v1/browsers/queue shows the line's length and your project's places in it, a held create by the Idempotency-Key it was sent with (browsers.queue() in the SDKs). Polling status or events does not keep a browser alive; only commands reset the idle timer.

In code

browser = client.browsers.create({"settings": {"locale": "en-US", "viewport": {"width": 1280, "height": 800}}})browser.ready()print(browser.navigate("https://example.com"))     # {"url": ..., "title": ...}for event in browser.events():    print(event["type"])browser.stop()

client.browsers.attach(id) gives the same handle for an instance created elsewhere.