Skip to main content
Actions are executed against a browser session via 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

wait_until controls when the action is considered complete:
  • load (default) — wait for the page load event.
  • dom_stable — wait until the DOM stops changing.
  • none — return immediately after navigation is initiated.
Navigation to domains not in the session’s 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:
Condition kinds:
  • { "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

Returns an artifact with 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_observation on 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

Add include_observation: true to any action to get a fresh observation in the response, saving a separate observe round-trip:
The response will include a new 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-level error 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 an unknown outcome may mean the action already took effect. A new idempotency key or a new session does not protect against duplicating those effects.
  1. If you have an action ID, retrieve that action and inspect its status. Also retrieve the session.
  2. 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.
  3. Without a known action ID or idempotency key, verify the outcome in the target application before repeating a mutation.
  4. Poll a provisioning session until ready. A closing, closed, failed, or expired session will not become ready again; use a new session for further work only after reconciling the original outcome. session_not_ready carries retryable: 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.