Control Flow
Repeat actions in a loop or run them only when a condition is met.
loop
Iterate over matching DOM elements or repeat a set of actions a fixed number of times.
each — loop over elements
Queries the page for all matching elements, then runs do once per element. The iteration count is fixed at the start — elements added to the DOM mid-loop are not picked up.
$this is available to target children of the current element.
[
{
"loop": {
"each": ".product-card",
"do": [
{ "getText": "$this h3", "options": { "push": "titles" } },
{ "getText": "$this .price", "options": { "push": "prices" } }
]
}
}
]
repeat — run N times
Runs do a fixed number of times. No DOM query is involved. $this is not available.
[
{
"loop": {
"repeat": 5,
"do": [
{ "scrollY": 800 },
{ "wait": 1000 }
]
}
}
]
Both modes are capped at 100 iterations by default. Override with "options": { "maxIterations": 200 }.
$this prefix
Inside an each loop, $this refers to the current element. Use it to target children within each iteration instead of searching the whole page:
| Usage | Meaning |
|---|---|
$this | The current element itself |
$this .child | .child inside the current element |
$this > span | Direct span child of the current element |
Selectors without $this always query the full page — you can mix scoped and global selectors in the same loop.
Options
| Option | Type | Default | Description |
|---|---|---|---|
maxIterations | number | 100 | Maximum number of iterations for both each and repeat |
Unsupported inside loop
screenshot, waitForResponse, and loop cannot be used directly inside a loop's do array.
To use a loop inside another loop, wrap the inner loop in an if block.
if
Run actions only when a condition is true. Optionally run different actions when it is false using else.
Value: { condition, then, else? }
Check whether an element exists on the page:
[
{
"if": {
"condition": ".cookie-banner",
"then": [
{ "click": ".cookie-banner .accept" }
],
"else": [
{ "click": "#continue" }
]
}
}
]
Compare an element's text or property:
[
{
"if": {
"condition": {
"selector": ".item-count",
"property": "textContent",
"operator": ">",
"value": "0"
},
"then": [
{ "click": "#checkout" }
]
}
}
]
Check a cached value:
[
{
"if": {
"condition": {
"cached": "totalItems",
"operator": ">=",
"value": "10"
},
"then": [
{ "click": "#bulk-discount" }
]
}
}
]
Condition types
| Type | Example | Description |
|---|---|---|
| String | ".selector" | Checks whether a matching element exists |
Object with selector | { selector, property, operator, value } | Reads a property from an element and compares it |
Object with cached | { cached, operator, value } | Compares a cached value |
Operators
| Operator | Description |
|---|---|
== | Equal |
!= | Not equal |
> | Greater than |
< | Less than |
>= | Greater than or equal |
<= | Less than or equal |
contains | Text contains value |
notContains | Text does not contain value |
matches | Regex match |
empty | Value is empty or null |
notEmpty | Value is not empty or null |
Nesting
loop and if can be nested inside each other. waitForResponse cannot be used inside if branches.
Example: Scrape Paginated Data
Loop through 5 pages, extract product data from each, and click "next" if available.
Note: to use a loop (the each) inside another loop (the repeat), the inner loop is wrapped in an if block.
[
{ "openNewTab": "https://example.com/products?page=1" },
{
"loop": {
"repeat": 5,
"do": [
{ "waitForElement": ".product-card" },
{
"if": {
"condition": ".product-card",
"then": [
{
"loop": {
"each": ".product-card",
"do": [
{ "getText": "$this .name", "options": { "push": "names" } },
{ "getText": "$this .price", "options": { "push": "prices" } }
]
}
}
]
}
},
{
"if": {
"condition": "a.next-page",
"then": [
{ "click": "a.next-page" },
{ "wait": 2000 }
]
}
}
]
}
},
{ "getSavedData": ["names", "prices"] }
]
Example: Dismiss Cookie Banner Before Screenshot
[
{ "openNewTab": "https://example.com" },
{ "waitForEvent": "networkidle" },
{
"if": {
"condition": ".cookie-banner",
"then": [
{ "click": ".cookie-banner .accept" },
{ "wait": 500 }
]
}
},
{ "screenshot": "viewport" }
]
Example: Check Element Text
[
{ "openNewTab": "https://example.com/status" },
{ "waitForElement": "#status" },
{
"if": {
"condition": {
"selector": "#status",
"property": "textContent",
"operator": "contains",
"value": "Success"
},
"then": [
{ "click": "#proceed" }
],
"else": [
{ "screenshot": "viewport" }
]
}
}
]