Commands API Reference

Every command, request field, response field, limit, and error code of the Steel Commands API.

POST /v1/sessions/{sessionId}/commands runs commands in a live session. The full schema is also in the API reference.

curl
1
curl -X POST https://api.steel.dev/v1/sessions/$SESSION_ID/commands \
2
-H "steel-api-key: $STEEL_API_KEY" \
3
-H "Content-Type: application/json" \
4
-H "Idempotency-Key: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d" \
5
-d '{ "commands": [{ "command": "snapshot", "interactive": true }] }'
HeaderRequiredMeaning
steel-api-keyYesYour API key.
Content-TypeYesapplication/json.
Idempotency-KeyNoA random value. A retry with the same key returns the stored result.

Request

FieldTypeMeaning
commandsobject or arrayOne command, or an array of up to 50. They run in order and stop at the first failure.
afterstringThe next value from your last response. A retry with the same after and commands runs only once.
observeobjectmode (none, snapshot, or diff), base (a snapshot id for diff), tab, and the snapshot options.
eventsAfterstringc-0 the first time, then the last events.cursor.

Fields that are not listed, or that a command does not take, fail with 400 invalid_request.

Response

Response
1
{
2
"next": "op_4f8k2m9q1x",
3
"epoch": 3,
4
"page": { "tab": "t1", "url": "https://example.com/", "title": "Example Domain" },
5
"execution": { "id": "x-2", "state": "completed", "effect": "applied", "replayed": false, "ran": 1 },
6
"results": [{ "ok": true, "effect": "applied" }],
7
"observe": { "snapshotId": "s-2", "base": "s-1", "diff": "...", "additions": 4, "removals": 2 }
8
}
FieldMeaning
nextSend it as after in your next request. Valid for an hour.
epochGoes up when commands or a dialog answer change the page, and when the browser restarts.
epochChangedtrue when another Commands API client changed the session since after.
pageThe tab the execution used, with its url and title.
executionid, state, effect, replayed, ran (commands started), and error when the execution ended early.
resultsOne entry per command that ran: ok, effect, the command's own fields, and error when it failed.
observesnapshotId with snapshot, or diff. A diff without a usable base returns the full snapshot with full: true.
dialogA dialog that is open on the tab and waits for an answer.
eventsNavigations, opened and closed tabs, dialogs, and downloads since eventsAfter: cursor, items, and more.
bodyExpiredtrue when a replay comes after its large parts expired.

effect is none when nothing changed, applied when the page changed, and unknown when it may have changed, for example after a timeout during input. Execution states are queued, running, completed, failed, cancelled, timeout, and expired.

Commands

CommandFieldsNotes
navigateurl, tabOnly http, https, and about:blank. A URL without a scheme gets https://. Waits up to 15 seconds for the page to load.
back, forwardtabReturns navigated: false when there is no history entry.
reloadtab
tabaction (list, new, close), tab, urllist returns tabs. The last tab cannot be closed.

Snapshot

CommandFieldsNotes
snapshottab, interactive, compact, depthReturns snapshotId and snapshot. interactive keeps only lines with refs. compact keeps lines with refs or values and their ancestors. depth limits the depth.
findby, value, name, exact, tab, frameReturns count and matches with refs, for up to 50 matches. by is a locator field, such as role or text. name works only with by: "role".

Elements

CommandFieldsNotes
click, dblclick, hovertargetScrolls the element into view and uses the mouse. Fails with not_actionable when something covers the element.
focustarget
typetarget, text, clear, delayTypes one key press at a time, after the current content. clear replaces the content. delay is milliseconds between key presses, up to 1000.
filltarget, valueReplaces the content in one step, without key presses. Date and time inputs take values like 2025-01-31.
presskey, targetKey names follow the US layout, such as Enter, ArrowDown, or Control+a.
selecttarget, valuesMatches options by value, then by label.
check, unchecktargetCheckboxes, radio buttons, switches, and toggle buttons.
scrolldirection, amount, targetScrolls the page, or the element in target. amount is pixels, 300 by default. Returns x, y, and moved.
uploadtarget, filesFile names from the session's files. Upload them first with the Files API.
dragsource, targetDrags with the mouse. HTML5 drag and drop works.

Input commands that start a navigation wait up to 15 seconds for the new page's DOM. When it is still loading, the result has loading: true.

Reading

CommandFieldsNotes
getwhat, target, attributeReturns value. See the values below.
iswhat (visible, enabled, checked), targetReturns value as true or false.
screenshottarget, fullPage, format, qualityReturns base64 data. format is png, jpeg, or webp.
pdftab, landscape, printBackgroundReturns base64 data. Works only in headless sessions.
evalscript, timeout, tabRuns JavaScript in the page and returns value as JSON. Waits for a promise to settle. Fails with script_error when the script throws.
get valueReturns
textThe text a person can see.
htmlThe HTML.
markdownThe page's main content as Markdown. With target, all of that element.
valueThe value of a field.
attrThe attribute named in attribute.
title, urlThe page title or URL.
countHow many elements match target.
boxThe element's box, in CSS pixels of the visible part of the page.
locatorWays to find the element again in a later session, best first.

Waiting

wait takes one of the conditions below, and an optional timeout in milliseconds. The default timeout is 10 seconds and the most is 50 seconds.

Request
1
{ "commands": [{ "command": "wait", "target": { "text": "Order placed" }, "timeout": 20000 }] }
FieldWaits for
target with stateThe element to be visible (default), hidden, attached, or detached.
textText on the page.
urlThe tab's URL to match. * matches any characters.
loadload, domcontentloaded, or networkidle.
msA fixed time, up to 30000 milliseconds.
downloadtrue waits for the next download to finish and returns file and bytes.

Keyboard and mouse

CommandFieldsNotes
keydown, keyupkey, tabHolds a key down, or lets it go. Held modifier keys apply to later input on the tab.
mouseaction (move, down, up, click, wheel), x, y, button, clicks, deltaX, deltaY, tabInput at a point, for pages without useful elements, such as a canvas. x and y are CSS pixels of the visible part of the page.

Control

CommandFieldsNotes
statusexecutionWaits for an execution and returns it.
cancelexecutionStops an execution.
dialogdialog, action (accept, dismiss), textAnswers an open dialog. The response is answered and epoch, not an execution.

status, cancel, and dialog run right away, outside the queue. Send each of them alone.

Targets

Element commands take target: a ref such as e12, a CSS selector, or a locator object. A locator sets exactly one of role, text, label, placeholder, alt, title, testid, or css.

Request
1
{
2
"commands": [
3
{
4
"command": "click",
5
"target": { "role": "button", "name": "Pay", "exact": true },
6
"frame": ["#checkout", { "title": "Payment" }],
7
"expect": { "role": "button" }
8
}
9
]
10
}
FieldMeaning
nameThe accessible name. Works only with role.
exactMatch the whole text. Text matches a case-insensitive substring by default. testid always matches exactly.
nthPicks one of several matches. Negative values count from the end.
frameThe iframe to look in, named like a target. List nested iframes from the outside in.
expectFails the command when the element does not have this role or name.
tabA tab id such as t2, for commands without a ref. A ref already knows its tab.

Limits

LimitValue
Commands per request50
Response wait20 seconds, then state: "running"
Execution run time60 seconds
Executions waiting per session16
navigate page load15 seconds
Page answer for each input10 seconds
wait and eval timeout10 seconds by default, 50 seconds at most
next and stored results1 hour
Large result parts10 minutes

Errors

Request errors have no execution. The body is { "error": { "code": ..., "message": ... } }.

StatusCodeMeaning
400invalid_requestThe body is not valid.
401Missing or invalid steel-api-key.
404session_not_foundThe session does not exist.
410session_endedThe session has ended. Create a new session.
422key_conflictThe Idempotency-Key was used with different commands.
422invalid_operation_tokenSteel no longer knows your after. The response carries a fresh next. Check the page first, because the commands may have run.
422unknown_executionstatus or cancel named an execution Steel does not know.
422dialog_not_pendingThe dialog was already answered or closed.
422missing_capabilityThe session's browser does not support commands. Create a new session.
429queue_full, records_fullToo much work in the session. Wait for Retry-After.
429expiredThe execution could not start in time.
503delivery_failedSteel could not reach the browser. Retry with the same Idempotency-Key.

An unexpected error inside the browser returns 200 with internal_error and no execution. Command errors appear in results[i].error with code, message, and sometimes reason.

CodeMeaning
stale_refThe ref's element left the page or shows other content. Take a new snapshot.
not_actionableThe element cannot take the input, for example because it is covered or disabled.
dialog_pendingA dialog waits for an answer on the tab.
element_not_foundNo element matches the target.
invalid_argumentA field has a bad value, or a locator matches several elements (ambiguous).
tab_not_found, tab_crashed, tab_requiredThe tab is missing, crashed, or has to be named because several are open.
frame_not_foundThe frame is missing or is not an iframe.
forbidden_url, forbidden_fileThe URL or file is not allowed.
navigation_failed, download_failedThe page or the download did not load.
script_errorThe eval script threw.
timeout, cancelledThe command ran out of time or was cancelled.
session_ended, browser_restartedThe session ended or the browser started again.
unknown_command, internal_errorThe command cannot run here, or Steel hit an unexpected error.

reason adds detail, such as covered, offscreen, no_box, disabled, read_only, not_editable, ambiguous, detached, content_changed, missing, or not_frame.