Control Flow Commands
Control flow commands let you add logic, loops, and error handling to your automations. Without them, your automation would simply run every command in order from top to bottom. With control flow commands, you can make decisions, repeat actions, and handle errors gracefully.
RTILA X provides seven control flow commands:
| Command | Purpose |
|---|---|
if / else |
Run commands conditionally based on a true/false condition |
while |
Repeat commands as long as a condition is true |
for_each |
Loop through items from a dataset or variable |
repeat |
Repeat commands a fixed number of times |
try_catch |
Handle errors gracefully without stopping the automation |
break |
Exit the current loop immediately |
continue |
Skip to the next iteration of the current loop |
Maximum Nesting Depth
Section titled “Maximum Nesting Depth”RTILA X supports a maximum nesting depth of 50 levels. This means you can nest control flow commands up to 50 levels deep. If you exceed this limit, the automation will stop with an error:
“Maximum command nesting depth exceeded.”
In practice, you’ll rarely need more than 5–10 levels of nesting. If you find yourself nesting deeply, consider breaking your automation into smaller, more focused projects.
if / else
Section titled “if / else”The if command runs a block of commands only if a condition is true. Optionally, you can provide an else block that runs when the condition is false.
Description
Section titled “Description”The if command evaluates a condition and then:
- If the condition is true, it runs the commands in the
thenblock. - If the condition is false and an
elseblock exists, it runs the commands in theelseblock. - If the condition is false and there’s no
elseblock, it skips to the next command.
Parameters
Section titled “Parameters”| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
condition |
object | ✅ Yes | — | The condition to evaluate. See condition types below. |
condition.type |
string | ✅ Yes | "element_visible" |
The type of condition. Options: element_visible, script, variable_contains. |
condition.selector |
string | If element_visible |
"" |
The selector to check for visibility. |
condition.iframe |
string | No | "" |
If the element is in an iframe, provide the iframe selector. |
condition.variable |
string | If variable_contains |
"" |
The name of the variable to check. |
condition.value |
string | If variable_contains |
"" |
The value to search for within the variable. |
condition.expression |
string | If script |
"" |
A JavaScript expression that returns true or false. |
then |
array | ✅ Yes | [] |
Commands to run if the condition is true. |
else |
array | No | [] |
Commands to run if the condition is false. |
Condition Types
Section titled “Condition Types”element_visible
Section titled “element_visible”Checks if an element is currently visible on the page.
{ "command": "if", "params": { "condition": { "type": "element_visible", "selector": "css=.cookie-banner" }, "then": [ { "command": "click", "params": { "selector": "css=.cookie-accept" } } ] }}script
Section titled “script”Evaluates a JavaScript expression. The expression has access to all state variables via the variables object.
{ "command": "if", "params": { "condition": { "type": "script", "expression": "variables.price > 100" }, "then": [ { "command": "comment", "params": { "text": "Price is over $100" } } ], "else": [ { "command": "comment", "params": { "text": "Price is $100 or less" } } ] }}variable_contains
Section titled “variable_contains”Checks if a variable’s value contains a specific string.
{ "command": "if", "params": { "condition": { "type": "variable_contains", "variable": "page_title", "value": "Error" }, "then": [ { "command": "comment", "params": { "text": "Page shows an error" } } ] }}Full Example: Cookie Banner Handling
Section titled “Full Example: Cookie Banner Handling”{ "command": "if", "params": { "condition": { "type": "element_visible", "selector": "css=.cookie-consent-banner" }, "then": [ { "command": "click", "params": { "selector": "css=.accept-all-cookies" } }, { "command": "wait", "params": { "timeout": 1000 } } ], "else": [ { "command": "comment", "params": { "text": "No cookie banner found" } } ] }}Behavior Notes
Section titled “Behavior Notes”- The
thenblock is required. Theelseblock is optional. - If the condition is false and there’s no
elseblock, the automation simply continues to the next command. - Conditions are evaluated at runtime, so they reflect the current state of the page.
- You can nest
ifcommands inside otherifcommands (up to 50 levels deep).
The while command repeats a block of commands as long as a condition remains true. It’s perfect for situations where you don’t know in advance how many times you need to repeat an action.
Description
Section titled “Description”The while command:
- Evaluates the condition.
- If the condition is true, runs the commands in the
doblock. - Goes back to step 1.
- If the condition is false, exits the loop and continues to the next command.
Parameters
Section titled “Parameters”| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
condition |
object | ✅ Yes | — | The condition to evaluate before each iteration. Same structure as if conditions. |
condition.type |
string | ✅ Yes | "element_visible" |
Options: element_visible, script, variable_contains. |
condition.selector |
string | If element_visible |
"" |
The selector to check. |
condition.expression |
string | If script |
"" |
JavaScript expression returning true/false. |
do |
array | ✅ Yes | [] |
Commands to run on each iteration. |
Example: Click “Load More” Until Gone
Section titled “Example: Click “Load More” Until Gone”{ "command": "while", "params": { "condition": { "type": "element_visible", "selector": "css=button.load-more" }, "do": [ { "command": "click", "params": { "selector": "css=button.load-more" } }, { "command": "wait", "params": { "timeout": 2000 } } ] }}This loop keeps clicking “Load More” until the button disappears.
Example: Loop Until a Variable Changes
Section titled “Example: Loop Until a Variable Changes”{ "command": "while", "params": { "condition": { "type": "script", "expression": "variables.has_more === true" }, "do": [ { "command": "extract_data", "params": { "dataset": "items" } }, { "command": "click", "params": { "selector": "css=.next-page" } }, { "command": "wait_for_load_state", "params": { "state": "networkidle" } }, { "command": "is_visible", "params": { "selector": "css=.next-page", "output_variable": "has_more" } } ] }}Behavior Notes
Section titled “Behavior Notes”- The condition is checked before each iteration, including the first one.
- If the condition is false from the start, the
doblock never runs. - Warning: Be careful with
whileloops. If the condition never becomes false, your automation will loop forever. Always include a way for the condition to become false (like clicking a “next” button that eventually disappears). - Use
breakinside the loop to exit early if needed. - The maximum nesting depth of 50 applies to
whileloops as well.
for_each
Section titled “for_each”The for_each command loops through items from a dataset or a list variable, running a block of commands for each item.
Description
Section titled “Description”The for_each command:
- Gets the list of items from a dataset or variable.
- For each item, stores it in a loop variable (default:
item). - Runs the commands in the
doblock. - Repeats for the next item.
Parameters
Section titled “Parameters”| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
source_type |
string | ✅ Yes | "dataset" |
Where to get the items. Options: dataset or variable. |
dataset |
string | If dataset |
"" |
The name of the dataset to iterate over. |
variable |
string | If variable |
"" |
The name of the list variable to iterate over. |
as |
string | No | "item" |
The name of the loop variable. Each item is stored in this variable during its iteration. |
do |
array | ✅ Yes | [] |
Commands to run for each item. |
Example: Loop Through a Dataset
Section titled “Example: Loop Through a Dataset”{ "command": "for_each", "params": { "source_type": "dataset", "dataset": "products", "as": "product", "do": [ { "command": "goto", "params": { "url": "${product.url}" } }, { "command": "extract_data", "params": { "dataset": "product_details" } } ] }}Example: Loop Through a List Variable
Section titled “Example: Loop Through a List Variable”{ "command": "set_variable", "params": { "name": "search_terms", "value": ["laptop", "tablet", "phone"] }},{ "command": "for_each", "params": { "source_type": "variable", "variable": "search_terms", "as": "term", "do": [ { "command": "goto", "params": { "url": "https://example.com/search?q=${term}" } }, { "command": "extract_data", "params": { "dataset": "results" } } ] }}Behavior Notes
Section titled “Behavior Notes”- The loop variable (specified by
as) is available inside thedoblock as${as}. - If
source_typeisdataset, the dataset must have been previously extracted usingextract_data. - If
source_typeisvariable, the variable must contain an array. - If the source is empty (no items), the
doblock never runs. - Use
breakto exit the loop early, orcontinueto skip to the next item. - The loop variable is overwritten on each iteration.
repeat
Section titled “repeat”The repeat command runs a block of commands a fixed number of times.
Description
Section titled “Description”The repeat command is the simplest loop. It runs the do block exactly times times, then continues to the next command.
Parameters
Section titled “Parameters”| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
times |
number | ✅ Yes | 5 |
The number of times to repeat the commands. Must be a positive integer. |
do |
array | ✅ Yes | [] |
Commands to run on each iteration. |
Example: Scroll Down 5 Times
Section titled “Example: Scroll Down 5 Times”{ "command": "repeat", "params": { "times": 5, "do": [ { "command": "scroll", "params": { "direction": "bottom" } }, { "command": "wait", "params": { "timeout": 1000 } } ] }}Example: Take 3 Screenshots
Section titled “Example: Take 3 Screenshots”{ "command": "repeat", "params": { "times": 3, "do": [ { "command": "screenshot", "params": { "path": "screenshot_${loop_index}.png" } }, { "command": "scroll", "params": { "direction": "by_pixels", "amount": 500 } } ] }}Behavior Notes
Section titled “Behavior Notes”timesmust be a positive integer. If it’s 0 or negative, thedoblock never runs.- The loop runs exactly
timestimes, regardless of what happens inside the loop. - Use
breakto exit early if needed. - The
repeatcommand is useful when you know exactly how many times you need to repeat an action.
try_catch
Section titled “try_catch”The try_catch command lets you handle errors gracefully. If a command in the try block fails, the automation doesn’t stop — instead, it runs the commands in the catch block.
Description
Section titled “Description”The try_catch command:
- Runs the commands in the
tryblock. - If all commands succeed, continues to the next command.
- If any command fails, stops the
tryblock and runs the commands in thecatchblock. - After the
catchblock, continues to the next command.
Parameters
Section titled “Parameters”| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
try |
array | ✅ Yes | [] |
Commands to attempt. If any command fails, the remaining commands in this block are skipped. |
catch |
array | No | [] |
Commands to run if any command in the try block fails. |
Example: Handle a Missing Element
Section titled “Example: Handle a Missing Element”{ "command": "try_catch", "params": { "try": [ { "command": "click", "params": { "selector": "css=.popup-close", "timeout": 3000 } } ], "catch": [ { "command": "comment", "params": { "text": "No popup found, continuing" } } ] }}Example: Retry with a Fallback Selector
Section titled “Example: Retry with a Fallback Selector”{ "command": "try_catch", "params": { "try": [ { "command": "click", "params": { "selector": "css=.primary-button" } } ], "catch": [ { "command": "comment", "params": { "text": "Primary button not found, trying fallback" } }, { "command": "click", "params": { "selector": "css=.secondary-button" } } ] }}Behavior Notes
Section titled “Behavior Notes”- If a command in the
tryblock fails, the remaining commands in thetryblock are skipped. - The
catchblock runs only if a command in thetryblock fails. - If the
catchblock is empty and a command fails, the error is silently ignored. try_catchdoes NOT catch errors in nested control flow commands (likeiforwhileinside thetryblock). It only catches errors in direct commands.- The error message is available in the
catchblock via thelast_errorvariable.
The break command immediately exits the current loop (while, for_each, or repeat).
Description
Section titled “Description”When RTILA X encounters a break command inside a loop, it immediately stops the loop and continues to the command after the loop.
Parameters
Section titled “Parameters”The break command has no parameters.
{ "command": "break", "params": {}}Example: Exit Loop When a Condition Is Met
Section titled “Example: Exit Loop When a Condition Is Met”{ "command": "while", "params": { "condition": { "type": "script", "expression": "true" }, "do": [ { "command": "extract_data", "params": { "dataset": "items" } }, { "command": "is_visible", "params": { "selector": "css=.next-page", "output_variable": "has_next" } }, { "command": "if", "params": { "condition": { "type": "script", "expression": "variables.has_next === false" }, "then": [ { "command": "break", "params": {} } ] } }, { "command": "click", "params": { "selector": "css=.next-page" } } ] }}Behavior Notes
Section titled “Behavior Notes”breakonly exits the innermost loop it’s inside.- If
breakis used outside a loop, it has no effect. breakis useful for creating loops that exit based on a condition checked inside the loop body.
continue
Section titled “continue”The continue command skips the rest of the current loop iteration and jumps to the next iteration.
Description
Section titled “Description”When RTILA X encounters a continue command inside a loop, it skips the remaining commands in the current iteration and jumps back to the beginning of the loop for the next iteration.
Parameters
Section titled “Parameters”The continue command has no parameters.
{ "command": "continue", "params": {}}Example: Skip Items That Don’t Match a Condition
Section titled “Example: Skip Items That Don’t Match a Condition”{ "command": "for_each", "params": { "source_type": "dataset", "dataset": "products", "as": "product", "do": [ { "command": "if", "params": { "condition": { "type": "script", "expression": "variables.product.price < 10" }, "then": [ { "command": "continue", "params": {} } ] } }, { "command": "goto", "params": { "url": "${product.url}" } }, { "command": "extract_data", "params": { "dataset": "details" } } ] }}This example skips products with a price less than $10.
Behavior Notes
Section titled “Behavior Notes”continueonly affects the innermost loop it’s inside.- If
continueis used outside a loop, it has no effect. continueis useful for filtering items inside a loop without using complexifconditions.
Nesting Control Flow Commands
Section titled “Nesting Control Flow Commands”You can nest control flow commands inside each other. Here’s an example of a complex nested structure:
{ "command": "for_each", "params": { "source_type": "dataset", "dataset": "categories", "as": "category", "do": [ { "command": "goto", "params": { "url": "${category.url}" } }, { "command": "while", "params": { "condition": { "type": "element_visible", "selector": "css=.product-card" }, "do": [ { "command": "extract_data", "params": { "dataset": "products" } }, { "command": "try_catch", "params": { "try": [ { "command": "click", "params": { "selector": "css=.next-page" } } ], "catch": [ { "command": "break", "params": {} } ] } } ] } } ] }}This example:
- Loops through categories.
- For each category, visits the category page.
- Loops through pages of products using
while. - Extracts products from each page.
- Tries to click “Next Page”. If it fails (no more pages), breaks out of the loop.
Nesting Depth Limit
Section titled “Nesting Depth Limit”Remember that RTILA X supports a maximum nesting depth of 50 levels. Each level of nesting (an if inside a while inside a for_each) counts as one level. If you exceed 50 levels, the automation stops with an error.
Control Flow Best Practices
Section titled “Control Flow Best Practices”| Practice | Description |
|---|---|
Use try_catch for optional elements |
Wrap clicks on elements that might not exist (like popups) in try_catch. |
Use while for unknown iterations |
When you don’t know how many pages to scrape, use while with a visibility condition. |
Use for_each for known lists |
When you have a list of items to process, use for_each. |
Use break to exit early |
Don’t rely on complex conditions — use break to exit loops when a condition is met. |
| Avoid infinite loops | Always ensure your while loops have a way to exit. Include a break or a condition that will eventually become false. |
| Keep nesting shallow | If you find yourself nesting more than 3–4 levels, consider breaking your automation into smaller projects. |
| Use comments | Add comment commands inside complex control flow to document your logic. |