Skip to content

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

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.


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.

The if command evaluates a condition and then:

  • If the condition is true, it runs the commands in the then block.
  • If the condition is false and an else block exists, it runs the commands in the else block.
  • If the condition is false and there’s no else block, it skips to the next command.
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.

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" } }
]
}
}

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" } }
]
}
}

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" } }
]
}
}
{
"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" } }
]
}
}
  • The then block is required. The else block is optional.
  • If the condition is false and there’s no else block, 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 if commands inside other if commands (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.

The while command:

  1. Evaluates the condition.
  2. If the condition is true, runs the commands in the do block.
  3. Goes back to step 1.
  4. If the condition is false, exits the loop and continues to the next command.
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.
{
"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.

{
"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"
}
}
]
}
}
  • The condition is checked before each iteration, including the first one.
  • If the condition is false from the start, the do block never runs.
  • Warning: Be careful with while loops. 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 break inside the loop to exit early if needed.
  • The maximum nesting depth of 50 applies to while loops as well.

The for_each command loops through items from a dataset or a list variable, running a block of commands for each item.

The for_each command:

  1. Gets the list of items from a dataset or variable.
  2. For each item, stores it in a loop variable (default: item).
  3. Runs the commands in the do block.
  4. Repeats for the next item.
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.
{
"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" } }
]
}
}
{
"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" } }
]
}
}
  • The loop variable (specified by as) is available inside the do block as ${as}.
  • If source_type is dataset, the dataset must have been previously extracted using extract_data.
  • If source_type is variable, the variable must contain an array.
  • If the source is empty (no items), the do block never runs.
  • Use break to exit the loop early, or continue to skip to the next item.
  • The loop variable is overwritten on each iteration.

The repeat command runs a block of commands a fixed number of times.

The repeat command is the simplest loop. It runs the do block exactly times times, then continues to the next command.

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.
{
"command": "repeat",
"params": {
"times": 5,
"do": [
{ "command": "scroll", "params": { "direction": "bottom" } },
{ "command": "wait", "params": { "timeout": 1000 } }
]
}
}
{
"command": "repeat",
"params": {
"times": 3,
"do": [
{ "command": "screenshot", "params": { "path": "screenshot_${loop_index}.png" } },
{ "command": "scroll", "params": { "direction": "by_pixels", "amount": 500 } }
]
}
}
  • times must be a positive integer. If it’s 0 or negative, the do block never runs.
  • The loop runs exactly times times, regardless of what happens inside the loop.
  • Use break to exit early if needed.
  • The repeat command is useful when you know exactly how many times you need to repeat an action.

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.

The try_catch command:

  1. Runs the commands in the try block.
  2. If all commands succeed, continues to the next command.
  3. If any command fails, stops the try block and runs the commands in the catch block.
  4. After the catch block, continues to the next command.
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.
{
"command": "try_catch",
"params": {
"try": [
{ "command": "click", "params": { "selector": "css=.popup-close", "timeout": 3000 } }
],
"catch": [
{ "command": "comment", "params": { "text": "No popup found, continuing" } }
]
}
}
{
"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" } }
]
}
}
  • If a command in the try block fails, the remaining commands in the try block are skipped.
  • The catch block runs only if a command in the try block fails.
  • If the catch block is empty and a command fails, the error is silently ignored.
  • try_catch does NOT catch errors in nested control flow commands (like if or while inside the try block). It only catches errors in direct commands.
  • The error message is available in the catch block via the last_error variable.

The break command immediately exits the current loop (while, for_each, or repeat).

When RTILA X encounters a break command inside a loop, it immediately stops the loop and continues to the command after the loop.

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" } }
]
}
}
  • break only exits the innermost loop it’s inside.
  • If break is used outside a loop, it has no effect.
  • break is useful for creating loops that exit based on a condition checked inside the loop body.

The continue command skips the rest of the current loop iteration and jumps to the next iteration.

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.

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.

  • continue only affects the innermost loop it’s inside.
  • If continue is used outside a loop, it has no effect.
  • continue is useful for filtering items inside a loop without using complex if conditions.

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:

  1. Loops through categories.
  2. For each category, visits the category page.
  3. Loops through pages of products using while.
  4. Extracts products from each page.
  5. Tries to click “Next Page”. If it fails (no more pages), breaks out of the loop.

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.


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.