Actions
Click, type, choose, scroll: options.actions runs steps in the page before the data is extracted. They run in a browser if you use one, and without one too: links are followed and forms are submitted with plain requests.
"options": {
"actions": [
{ "fill": "#q", "value": "lamp" },
{ "click": "#go" }
]
}See it work
The demo shop has a search form with a hidden security token. Fill it in and submit it, without a browser: the API reads the form, keeps the hidden token and the session cookie, and posts it like a browser would:
Actions
Data
The response tells you what each action did:
"actions": [
{
"action": "fill",
"status": "emulated",
"detail": "set the field's value for the next form submission"
},
{
"action": "select",
"status": "emulated",
"detail": "set the field's value for the next form submission"
},
{
"action": "click",
"status": "emulated",
"detail": "submitted the form as POST /demo/shop/search"
}
]The "Gift ideas" button only works with JavaScript. Without a browser it's skipped; with one, it runs:
Actions
Data
Ready-made recipes for pagination, "Load more" buttons, cookie banners, forms and infinite scroll are in Recipes.
Available actions
Each action is an object with one action name:
| Action | Example | What it does |
|---|---|---|
click | { "click": "a.next" } | Clicks the first element matching the selector. "all": true clicks every match |
fill | { "fill": "#q", "value": "lamp" } | Sets a field's value at once |
type | { "type": "#q", "value": "lamp" } | Types the value key by key, like a person |
select | { "select": "#sort", "value": "price" } | Chooses an option by value or visible label |
check, uncheck | { "check": "#terms" } | Ticks or unticks a checkbox or radio |
hover | { "hover": ".menu" } | Moves the mouse over an element |
double_click | { "double_click": ".cell" } | Double-clicks an element |
press | { "press": "Enter" } | Presses a key. "selector" focuses an element first |
scroll | { "scroll": "bottom", "times": 3, "delay": 800 } | Scrolls to "top", "bottom", by a number of pixels, or to an element (CSS selector). times repeats it (infinite scroll), delay waits between scrolls (default 500 ms) |
wait | { "wait": 1000 } | Waits, in ms (30 s max) |
wait_for | { "wait_for": ".results", "timeout": 30000 } | Waits for an element. "state": visible (default), attached, hidden or detached. "timeout": how long, in ms (120 s max; default: the request's timeout) |
navigate | { "navigate": "https://example.com/page-2" } | Opens another page |
reload | { "reload": true } | Loads the current page again |
back | { "back": true } | Goes back to the previous page |
evaluate | { "evaluate": "document.title" } | Runs JavaScript in the page; the result is reported in detail |
solve_captcha | { "solve_captcha": true } | Solves the captcha on the page and hands the answer to it. See Captchas |
screenshot | { "screenshot": { "full_page": true } } | A screenshot at this moment, in the action's result (file). Same options as options.screenshot |
pdf | { "pdf": true } | A PDF at this moment, in the action's result (file). Same options as options.pdf |
ai | { "ai": "accept the cookies, then load every product" } | What to do, in plain words: see below |
Up to 50 actions per request. The data is extracted from the page as it is after the last action.
AI actions
Describe what to do instead of writing selectors: { "ai": "…" } reads the page's buttons, links and fields, and turns the instructions into the actions above.
Actions
Data
The result lists the actions it ran, so you can copy them into a request without AI:
{
"action": "ai",
"status": "done",
"detail": "5 action(s)",
"ai": {
"actions": [{ "click": "#accept" }, { "click": "#load-more" }, { "wait": 1000 }, { "click": "#load-more" }, { "wait": 1000 }],
"cached": false,
"cost_usd": 0.0003
}
}- Remembered: the plan is kept per site page and instructions (numbers and ids in the path don't count, so
/product/12and/product/13share it). Later requests replay it without calling the model:"cached": true, and no AI credits. - Repaired: when a remembered action no longer works (the site changed), the model plans the rest again from the current page, and the new plan replaces the old one.
- Plans are kept per account: instructions may hold values you don't want shared.
- One element in plain words works in any action that takes a selector:
{ "click": { "ai": "the Load more button" } },{ "fill": { "ai": "the search box" }, "value": "lamp" }. It's anaiaction for that one step, remembered the same way. - It needs a browser, and is billed like an AI call only when the model is asked.
With and without a browser
The same actions work in both cases. Without a browser, what a plain request can do is emulated, and the rest is skipped, never fatal:
| Action | In a browser | Without a browser |
|---|---|---|
click on a link | clicks | follows the link (GET) |
click on a submit button | clicks | submits its form: every field, hidden ones included, as GET or POST like the form says |
click on a checkbox or its label | clicks | ticks or unticks it for the next submission |
click on an element whose onclick sets location | clicks | follows that address |
click on anything else | clicks | skipped: the behaviour is JavaScript |
fill, type, select, check, uncheck | runs | sets the value for the next form submission |
press Enter | presses | submits the form of the last field filled |
navigate, reload | opens | GET |
wait | waits | waits before the next request |
solve_captcha | solves it in the page | solves a captcha the HTML shows; its token goes with the next form submission (see Captchas) |
wait_for | waits | checks the HTML once |
scroll, hover, double_click, back, evaluate, screenshot, pdf, ai | runs | skipped |
When an action is skipped, a warning suggests setting options.browser.
Results
actions in the response lists each action in order:
status | Meaning |
|---|---|
done | Ran in the browser |
emulated | Done without a browser; detail says how |
skipped | Can't be done without a browser; detail says why |
failed | An optional action that failed in the browser |
When an action fails
In a browser, an action fails when its element doesn't appear before the timeout: the request stops with 422 ACTION_FAILED, naming the action:
{
"error": {
"code": "ACTION_FAILED",
"message": "actions[1] (click) failed: Timeout 15000ms exceeded."
}
}Mark an action "optional": true to carry on instead, like closing a cookie banner that isn't always there:
"actions": [
{ "click": "#accept-cookies", "optional": true },
{ "click": "#load-more" }
]ACTION_FAILED triggers fallback strategies, so you can try another engine, or no browser at all, when an action fails.