409 session_busy if the previous operation is still running.
Each call counts as one action under the drive rate limit. By default, calls use the tab shown in the live viewer. The navigate and tabs endpoints support selecting another tab.
A main CDP client, native Playwright client, or VNC client holds the session, so REST drive calls and fetch return 409 session_driven_by_client. Disconnect that client before driving over REST. CDP observers do not hold the session and can remain connected. Coordinate their commands with REST actions because all clients share the browser.
POST /v1/session/{session_id}/navigate
Open a URL in a tab that stays open, so lateract, elements, screenshot calls and the live view work on it. The page is checked for walls and challenges; when the landing is blocked or off target the API tries to recover inside this session before answering. Recovery here stays on the session’s own exit; POST /v1/fetch is the route that may escalate to stronger exits, so use fetch for a protected page and navigate for an interactive flow on a page you can already reach.
Request:
expect_text, no_results_url, wait_ms, settle_ms and wait_for_selector belong to POST /v1/fetch; sent here they are ignored.
An off-target landing (
expect_url did not match):
isp and residential rungs read unavailable with navigate_keeps_the_callers_session: a navigate never moves your session to another exit, because the tab, cookies and live view have to stay yours. POST /v1/fetch is the route that may climb to stronger exits.
A page the origin does not have (recovery trimmed):
https://httpbin.org/cookies/set/sessionid/abc123 lands on /cookies): 200, status: "redirected_off_target", error: "collapsed_to_entry", redirected: true, final_url: "https://httpbin.org/cookies". The page is open and usable (the cookie was set); the status tells you the URL moved.
Errors:
Notes: a plain page answers in about half a second. A navigation that needs recovery runs up to 55 seconds (
budget.total_s) and then answers status: "error", error: "deadline", failure_type: "TimeoutError".
POST /v1/session/{session_id}/act
A human-style input on the current page: click, type, fill, press a key, scroll, set the clipboard, or wait for an element. UsePOST .../elements first to get a selector that resolves to one element.
Request:
fill replaces the field’s value; type types into the selector, or into the focused element when no selector is given. wait_for waits for the selector to appear (about 10 seconds, then 404). set_clipboard puts text on the session’s clipboard so a person on the live view can paste it.
Response fields:
ok (boolean), action (echo), error (null, or a slug when ok is false with status 200, for example incomplete_observation when the page could not be observed after the action).
Errors (the session stays alive on all of them):
As returned:
elements, screenshot or fetch sees the result of the action. The first action after a navigate can take longer while the page is observed; later actions on the same page are sub-second. One action per call, 1 credit each.
POST /v1/session/{session_id}/elements
List the actionable elements on the current tab, each with a selector that resolves back to that one element. This is the discovery step beforeact. Input values are never returned, only their length.
Request:
https://example.com/ with an empty body:
ok; count (rows returned); matched (rows that passed the filters); elements[] with selector, tag, and when present name (accessible name), href, type, input_name, value_len; truncated (true when matched exceeds count: narrow with selector or text rather than raising limit). A selector that matches nothing answers 200 with count: 0.
Errors: 400 bad_selector for a selector the browser cannot parse; 404 element_not_found; 409 session has no open tab; 409 session_busy when another call is driving; 409 session_driven_by_client when a main CDP, native Playwright, or VNC client holds the session; 502 Data Plane element read failed when the page could not be read. 1 credit per call on credit-funded accounts.
POST /v1/session/{session_id}/screenshot
Capture the current tab as an image, base64 in JSON. Request:ok, session_id, format, full_page, image_base64 (the image), data_url (the same with a data: prefix, ready for an <img> or a vision model), size_b64 (characters of base64; the PNG or JPEG is about three quarters of that in bytes).
Errors: 400 bad_selector (detail: "screenshot element unavailable") when the element cannot be captured; fall back to the viewport; 404 element_not_found for a selector that matches nothing; 409 session_busy when another call is driving; 409 session_driven_by_client when a main CDP, native Playwright, or VNC client holds the session; 502 Data Plane screenshot failed. Billing: 1 action plus the base64 size in MB as egress on credit-funded accounts.
GET /v1/session/{session_id}/tabs
Every open tab, oldest first. Free; counts under the drive throttle.max reports the session’s tab limit; do not hardcode it. index is the position in this list; tab_id is what navigate and DELETE .../tabs/{tab_id} take.
POST /v1/session/{session_id}/tabs
Open a tab, optionally at a URL, and return it. 201 on success. Request:url (optional, max 4096, http(s), same address rules as navigate).
{"tab_id": "84C437990B422ACB5A9893AB52832AB5", "index": 2, "url": "about:blank", "title": ""}.
A navigate aimed at the new tab, {"url": "https://example.com/", "tab_id": "21FEA677628AF1C2FFD0F465AEA076C5"}, drives that tab and leaves the first where it was.
Errors: 400 for a blocked url; 429 tab_limit with the applicable limit; 502 Data Plane tab creation failed when the tab or its initial navigation could not be created. Read /tabs for the session’s max. 1 credit per tab opened on credit-funded accounts.
DELETE /v1/session/{session_id}/tabs/{tab_id}
Close one tab. 204 with no body. Errors: 404No such tab for an unknown or already closed id; 409 last_tab when it is the only tab, because a session with no tab cannot be driven; delete the session instead.
GET /v1/session/{session_id}/context
Export the current tab’s auth state (cookies, localStorage, sessionStorage) as JSON you store yourself. Hand it back withPOST .../context on a later session to skip a login.
Response after visiting https://httpbin.org/cookies/set/sessionid/abc123 (200):
Data Plane context read failed.
POST /v1/session/{session_id}/context
Restore an exported context into a live session, then optionally navigate. Cookies are applied before the navigation, so the very first request is already authenticated. Request:applied counts what really landed, so a zero tells you the origin refused the state rather than reporting success. Errors: 400 context requires an HTTP(S) origin when neither url nor context.url is an http(s) URL; 502 when the navigation failed, with the reason as the body. A restore with url is one action (1 credit); without it the call is free.
POST /v1/session/{session_id}/files/fetch
Download a file through the session’s browser and return its bytes. The request is made by the page itself, with the session’s cookies and TLS identity, so files behind a login work. Request:url (required, max 4096); max_bytes (optional, at least 1) to accept less than the 32 MiB cap.
filename comes from the final URL’s last path segment (download when there is none), size is the byte count, content_base64 the file.
Errors:
Billing: 1 action plus the file size in MB as egress.
POST /v1/session/{session_id}/rotate-ip
Move the session to a fresh exit IP without changing the browser, cookies or tabs. Sessions keep one exit by default; call this when a site starts refusing, or between logical tasks. No body. Custom-proxy sessions return409 customer_proxy_session. Change the exit through your proxy provider instead.
region is where the new exit sits. fresh_allocation is true when a brand-new address was allocated for the session, false when it moved to another address from the pool. On a residential session the session gets a new residential exit and fresh_allocation is true.
Errors: 409 with a reason slug when no rotation is possible right now (ip_rotation_unavailable, exit_ladder_exhausted, residential_rotation_unavailable); 503 rotation_timeout with Retry-After, leaving the session open; 402 and 429 like every drive call. A CDP client stays connected across the rotation. 1 credit on credit-funded accounts.