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.
{ "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.
| Setting | Meaning |
|---|---|
locale, timezone | The browser's locale and time zone in direct mode; a proxied browser takes both from the exit's GeoIP instead |
viewport | Width and height |
idle_timeout_ms | Stop after this long without a command; default 600000 |
timeout_ms | Total lifetime; default 1800000. Both lifetimes range 1000–3600000 |
record_video | Record the page as VP8 WebM — see Downloads and recordings |
network | direct, managed or custom — see Network |
navigation | allow / block host patterns and block_raw_ip; a refused navigation is navigation_blocked (409) |
profile_id | Start 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
| Status | Meaning |
|---|---|
starting | Launching |
running | Ready for commands |
stopping | A stop is in progress |
stopped | Released; stop_reason says why (requested, idle, lifetime, credential_revoked, …) |
failed | Launch or Worker failure; error carries the code |
cleanup_failed | Release 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()const browser = await client.browsers.create({ settings: { locale: 'en-US', viewport: { width: 1280, height: 800 } } });await browser.ready();console.log(await browser.navigate('https://example.com')); // { url, title }for await (const event of browser.events()) console.log(event.type);await browser.stop();client.browsers.attach(id) gives the same handle for an instance created elsewhere.
