> ## Documentation Index
> Fetch the complete documentation index at: https://docs.optexity.com/llms.txt
> Use this file to discover all available pages before exploring further.

# For Loop Node

> Iterating over multiple values in automations

Use `for_loop_node` to repeat actions for each value in a list—processing search results, downloading multiple files, or clicking through items.

## Structure

```json theme={null}
{
  "type": "for_loop_node",
  "variable_name": "order_ids",
  "nodes": [
    {
      "type": "action_node",
      "interaction_action": {
        "click_element": {
          "command": "get_by_text(\"{order_ids[index]}\")",
          "prompt_instructions": "Click order {order_ids[index]}"
        }
      }
    }
  ],
  "reset_nodes": [],
  "on_error_in_loop": "raise"
}
```

## Properties

| Property           | Type                                | Description                         |
| ------------------ | ----------------------------------- | ----------------------------------- |
| `variable_name`    | `str`                               | Parameter to iterate over           |
| `nodes`            | `list[action_node \| if_else_node]` | Actions for each iteration          |
| `reset_nodes`      | `list[action_node \| if_else_node]` | Actions to run after each iteration |
| `on_error_in_loop` | `"continue" \| "break" \| "raise"`  | Error handling behavior             |

## The `index` Variable

Inside a loop, `{variable[index]}` references the current iteration's value:

```
order_ids = ["ORD-001", "ORD-002", "ORD-003"]

Iteration 1: {order_ids[index]} → "ORD-001"
Iteration 2: {order_ids[index]} → "ORD-002"
Iteration 3: {order_ids[index]} → "ORD-003"
```

### Using Multiple Variables in a Loop

You can iterate over **multiple parameters in parallel** by passing a **comma-separated list** to `variable_name`.

**Important:** The **first** in `variable_name` is the **main loop variable** that controls:

* How many iterations run (loop length)
* Which index is used for each step

All additional names in the list are **synced to the same index**. In other words:

* `variable_name: "primary_var,secondary_var"` → loop length comes from `primary_var`
* `{primary_var[index]}` and `{secondary_var[index]}` both use the **same** `index` on each iteration

For each iteration, `{variable[index]}` is expanded for **every** name in the list:

```json theme={null}
{
  "type": "for_loop_node",
  "variable_name": "primary_var,secondary_var",
  "nodes": [
    {
      "type": "action_node",
      "interaction_action": {
        "input_text": {
          "command": "get_by_role(\"textbox\", name=\"Primary Field\")",
          "input_text": "{primary_var[index]}"
        }
      }
    },
    {
      "type": "action_node",
      "interaction_action": {
        "input_text": {
          "command": "get_by_role(\"textbox\", name=\"Secondary Field\")",
          "input_text": "{secondary_var[index]}"
        }
      }
    }
  ]
}
```

If your parameters are:

* `primary_var = ["Value A1", "Value A2"]`
* `secondary_var = ["Value B1", "Value B2"]`

Then:

* Iteration 1 uses `{primary_var[index]}` → `"Value A1"` and `{secondary_var[index]}` → `"Value B1"`
* Iteration 2 uses `{primary_var[index]}` → `"Value A2"` and `{secondary_var[index]}` → `"Value B2"`

## Data Sources

Loop variables can come from:

| Source                 | When to Use                          |
| ---------------------- | ------------------------------------ |
| `input_parameters`     | Known values before execution        |
| `generated_parameters` | Values extracted during automation   |
| `secure_parameters`    | Sensitive values from secure storage |

For dynamic iteration, extract values first:

```json theme={null}
[
  {
    "type": "action_node",
    "extraction_action": {
      "llm": {
        "extraction_format": { "item_ids": "List[str]" },
        "output_variable_names": ["item_ids"],
        "extraction_instructions": "Extract all item IDs"
      }
    }
  },
  {
    "type": "for_loop_node",
    "variable_name": "item_ids",
    "nodes": [ ... ]
  }
]
```

## Reset Nodes

Actions that run **after each iteration** to return the browser to a known state. Essential for loops that navigate away from the starting page.

```json theme={null}
{
  "type": "for_loop_node",
  "variable_name": "documents",
  "nodes": [
    {
      "type": "action_node",
      "interaction_action": {
        "click_element": {
          "command": "get_by_text(\"{documents[index]}\")"
        }
      }
    }
  ],
  "reset_nodes": [
    {
      "type": "action_node",
      "interaction_action": {
        "close_tabs_until": {
          "matching_url": "https://example.com/documents"
        }
      }
    }
  ]
}
```

### Reset Strategy Recommendations

| Action                   | Reliability | Use When                     |
| ------------------------ | ----------- | ---------------------------- |
| `close_tabs_until`       | High        | Actions open new tabs        |
| `go_to_url`              | High        | Navigate to known URL        |
| `click_element` (navbar) | Medium      | Persistent navigation exists |
| `go_back`                | Low         | Avoid—fails on errors        |

<Warning>
  Avoid `go_back` for reset nodes. If an error occurs mid-loop, the browser may be on an unexpected page.
</Warning>

## Error Handling

| Behavior     | Description                                     |
| ------------ | ----------------------------------------------- |
| `"raise"`    | Stop automation on error (default)              |
| `"continue"` | Skip failed iteration, continue to next         |
| `"break"`    | Stop loop, continue with next node outside loop |

```json theme={null}
{
  "type": "for_loop_node",
  "variable_name": "files",
  "on_error_in_loop": "continue",
  "nodes": [ ... ]
}
```

<Tip>
  Use `"continue"` when some items may fail but you want to process as many as possible (e.g., downloading files where some may be missing).
</Tip>

## Common Patterns

### Download Multiple Files

```json theme={null}
{
  "type": "for_loop_node",
  "variable_name": "doc_links",
  "nodes": [{
    "type": "action_node",
    "interaction_action": {
      "click_element": {
        "command": "get_by_role(\"link\", name=\"{doc_links[index]}\")",
        "expect_download": true,
        "download_filename": "{doc_links[index]}.pdf"
      }
    }
  }]
}
```

### Process Items and Return

```json theme={null}
{
  "type": "for_loop_node",
  "variable_name": "item_ids",
  "nodes": [
    {
      "type": "action_node",
      "interaction_action": {
        "click_element": {
          "command": "get_by_text(\"{item_ids[index]}\")"
        }
      }
    },
    {
      "type": "action_node",
      "extraction_action": {
        "llm": {
          "extraction_format": { "details": "str" },
          "extraction_instructions": "Extract item details"
        }
      }
    }
  ],
  "reset_nodes": [{
    "type": "action_node",
    "interaction_action": {
      "go_to_url": { "url": "https://example.com/items" }
    }
  }]
}
```

## Limitations

* Nested loops are not supported
* Variable must be populated before loop execution
* Only `action_node` and `if_else_node` allowed inside loops
