POST /v2/browser_sessions/:id/actions. Each session executes one action at a time.
Action Types
All actions accept optional
include_observation (bool, default false) and idempotency_key (string).
Common Fields
Navigation
wait_until controls when the action is considered complete:
load(default) — wait for the pageloadevent.dom_stable— wait until the DOM stops changing.none— return immediately after navigation is initiated.
allowed_domains returns HTTP 200 with the action in status: "failed" and data.error.code: "policy_denied" — execution failures like this are reported on the action resource, not as HTTP error statuses.
Press
Scroll
Wait For
Wait for a condition to be met on the page:{ "kind": "url_pattern", "pattern": "*/login" }— wait until the URL matches a pattern.{ "kind": "ref", "observation_id": "obs_...", "ref": "e1" }— wait for an element to appear.{ "kind": "text", "text": "Welcome" }— wait for text to appear on the page.{ "kind": "dom_stable" }— wait until the DOM stops changing.
Screenshot
artifact_id, content_type, and size_bytes. Download via:
Batch Actions
Execute multiple actions in a single request. Sub-actions run sequentially. A failed sub-action stops the batch (non-atomic — prior mutations persist).actions[]— 1 to 50 sub-actions. An empty array is rejected (400), and the array is non-recursive (batch inside batch → 400).include_observationon a batch applies to the last sub-action only.- A failed sub-action stops the batch with
status: "failed". Earlier sub-actions have already mutated the browser (they are not rolled back), but partial sub-action results are not returned —results[]is present only when every sub-action completes.
include_observation
Addinclude_observation: true to any action to get a fresh observation in the response, saving a separate observe round-trip:
observation_id and refs for the resulting page.
Action Failures vs HTTP Errors
There are two distinct error surfaces: Request errors use HTTP error statuses and a top-levelerror object. The Code column is error.code:
Session creation, not action submission, returns the session quota error below. See Sessions.
Execution failures are returned on the action resource inside HTTP 200 as
data.status: "failed" (or unknown) with data.error:
These codes travel in
data.error.code inside an HTTP 200 response — the HTTP column records that carrier status, not a request failure. A failed or unknown action is terminal. Inspect the cause and any effects before deciding whether a new action is safe. For staleness, obtain a fresh observation and select a current ref.
Recovering from execution_lost
Do not blindly resubmit a mutation: a lost response or anunknown outcome may mean the action already took effect. A new idempotency key or a new session does not protect against duplicating those effects.
- If you have an action ID, retrieve that action and inspect its status. Also retrieve the session.
- If the original submission included
idempotency_key, repeating the same normalized request with the same key on the same session retrieves an existing record when one exists, even after the session closes. It does not re-execute a terminal action. If no record exists, that submission can start a new action; only attempt it when safe. - Without a known action ID or idempotency key, verify the outcome in the target application before repeating a mutation.
- Poll a
provisioningsession until ready. Aclosing,closed,failed, orexpiredsession will not become ready again; use a new session for further work only after reconciling the original outcome.session_not_readycarriesretryable: true, but that flag does not make a terminal session reusable.
Polling Actions
wait_seconds (0–25, default 10) limits only how long the submission request waits, not execution time. If the action is still queued or running, the response is 202 Accepted; execution continues. Poll the returned action ID rather than submitting it again. GET returns HTTP 200 even while the action is still running, so inspect data.status:
Full observation tree and refs are delivered only in the original successful submission response when it completes within the wait. Polling and idempotent replays return observation metadata with an empty tree and refs. If you need element refs after polling, submit a new observe with wait_seconds=25; see Get Started.