The `actions` array runs in order once the page has loaded. It works in **`mode: "browser"`
only
Available actions
- `wait` — fields `selector?`, `milliseconds?`. Waits for a selector to appear, or for a
fixed duration.
- `click` — field `selector`. Clicks the element.
- `scroll` — fields `direction?`, `amount?`, `selector?`. Defaults to down / 800 px and
scrolls smoothly in 10 steps 30 ms apart.
- `scrape` — field `selector?`. Takes an HTML snapshot at that moment; results come back
in `actions_result.scrapes[]`.
- `write` — fields `text`, `selector?`. Types text, into the focused element if no
selector is given.
- `press` — field `key`. Presses a keyboard key, such as `"Enter"` or `"Escape"`.
- `executeJavascript` — field `code`. Runs JavaScript; the return value arrives in
`actions_result.scripts_results[]`. The legacy `script` field is accepted and normalised
to `code`.
- `screenshot` — field `selector?`. Returns a base64 PNG in `actions_result.screenshots[]`.
The legacy `fullPage` field is accepted.
- `fill_form` — fields `fields` (each with `selector` and `value`) and `submit?`.
- `loop` — fields `maxIterations`, `actions`, `stopWhen?`. Repeats the inner action list.
Basic example
"actions": [
{ "type": "wait", "milliseconds": 1000 },
{ "type": "click", "selector": "#accept-cookies" },
{ "type": "scroll", "direction": "down", "amount": 800 },
{ "type": "wait", "selector": ".product-grid" }
]Scrolling inside an element
With a `selector`, scrolling happens inside that element and the page itself stays put —
which is what infinite-scroll lists and scrollable dropdowns need.
{ "type": "scroll", "selector": "#results-list", "amount": 1000 }If the selector matches no element, the action fails and so does the request.
Exhausting an infinite scroll
Use `loop` to repeat the scroll and take a snapshot on each pass.
{
"type": "loop",
"maxIterations": 10,
"actions": [
{ "type": "scroll", "selector": "#results-list", "amount": 1200 },
{ "type": "wait", "milliseconds": 800 },
{ "type": "scrape", "selector": "#results-list" }
]
}The snapshots arrive in order in `actions_result.scrapes[]`. This is the most practical way
to consume a paginating site.
Filling a form
{
"type": "fill_form",
"fields": [
{ "selector": "input[name=custname]", "value": "John Doe" },
{ "selector": "input[name=custemail]", "value": "john@example.com" },
{ "selector": "select#size", "value": "large" },
{ "selector": "input[name=topping][value=bacon]", "value": "true" },
{ "selector": "textarea[name=comments]", "value": "Ring the bell" }
],
"submit": "button[type=submit]"
}- Use `value: "true"` for checkboxes and radio buttons.
- With `submit`, that element is clicked and navigation is awaited.
- This is the correct way to submit an HTML form in browser mode; `options.method: "POST"`
is rejected there.
Running JavaScript
{ "type": "executeJavascript", "code": "return document.querySelectorAll('.item').length" }Screenshots
{ "type": "screenshot", "selector": ".product-detail" }Order matters. Dismiss overlays first, always put a `wait` after an interaction so the DOM
can update, call `scrape` only once the data is on screen, and raise
`options.timeout_seconds` as the action chain grows.