ScreenshotNeo

BlogHow-to

How to Use For Loops in Robot Framework

Learn Robot Framework FOR loops for lists, ranges, paired values, and dictionaries, with control flow, version notes, runnable examples, and troubleshooting.

By the ScreenshotNeo team4 October 20267 min read

Use a block loop in Robot Framework: start with FOR, choose IN or a specialized marker such as IN RANGE, put the repeated keyword calls in the body, and close the loop with END. The examples below use the current syntax; legacy :FOR syntax was removed in Robot Framework 4.0.

1. Basic FOR loop syntax

A loop assigns the next value to its loop variable on each iteration. Loop markers are case-sensitive. Indent the body to make the block easier to scan.

*** Test Cases ***
Process Items
    FOR    ${item}    IN    apple    banana    cherry
        Log    Processing ${item}
    END

Use the same structure in a test case or a user keyword. For a list variable, expand the list with @{} in the loop header:

*** Test Cases ***
Process Items From List
    @{items}=    Create List    apple    banana    cherry
    FOR    ${item}    IN    @{items}
        Log    Processing ${item}
    END

Each pass assigns one list item to ${item}. Keep the loop body focused; move complicated work into a user keyword so the test reads as a sequence of actions.

2. Choose the loop form that matches your data

Input or need Loop form What gets assigned
Values or a list FOR ${item} IN ... One value per iteration
Generated numeric positions FOR ${index} IN RANGE ... Numbers in a range; the end is excluded
Value and its position FOR ${index} ${item} IN ENUMERATE ... Index and corresponding item
Corresponding values in lists FOR ${a} ${b} IN ZIP ... One value from each list in each pass
Dictionary entries FOR ${key} ${value} IN ${dict} Key and value

Iterate over a numeric range

IN RANGE generates numeric values. A single argument is the exclusive end, so IN RANGE 10 produces 0 through 9. You can provide start, end, and step; a negative step counts downward. Float parameters are supported.

*** Test Cases ***
Check Rows
    FOR    ${index}    IN RANGE    1    4
        Log    Checking row ${index}
    END

This iterates over 1, 2, and 3. Avoid assuming the end value is included.

Keep an item and its index with IN ENUMERATE

IN ENUMERATE assigns an index and item together. The default index begins at zero. Robot Framework 4.0 and later supports a custom starting index using start=.

*** Test Cases ***
Log Numbered Items
    @{items}=    Create List    alpha    beta
    FOR    ${index}    ${item}    IN ENUMERATE    @{items}
        Log    ${index}: ${item}
    END

Start Numbering At One
    @{items}=    Create List    alpha    beta
    FOR    ${index}    ${item}    IN ENUMERATE    @{items}    start=1
        Log    ${index}: ${item}
    END

Use IN ZIP when values from different lists belong together by position. The number of loop variables should match the number of collections.

*** Test Cases ***
Check User Records
    @{ids}=      Create List    u-101    u-102
    @{names}=    Create List    Ada      Lin
    FOR    ${id}    ${name}    IN ZIP    ${ids}    ${names}
        Log    Checking ${id} for ${name}
    END

Iterate over dictionary entries

Use two loop variables with a dictionary to receive each key and its value:

*** Test Cases ***
Log Settings
    &{settings}=    Create Dictionary    theme=dark    retries=3
    FOR    ${key}    ${value}    IN    &{settings}
        Log    ${key}=${value}
    END

Assign several values per iteration

A loop can have multiple variables before IN. In an ordinary value sequence, the values must divide evenly among the loop variables. Choose a specialized form such as IN ZIP when it better expresses paired collections.

3. Nested loops and loop control

Nested FOR loops are supported from Robot Framework 4.0. They are useful for simple combinations, such as rows and cells. Keep multiple levels readable, and extract complex actions into user keywords.

*** Test Cases ***
Visit Table Cells
    @{rows}=    Create List    header    body
    @{columns}=    Create List    name    status
    FOR    ${row}    IN    @{rows}
        FOR    ${column}    IN    @{columns}
            Log    Checking ${row}, ${column}
        END
    END

BREAK exits the loop, while CONTINUE skips the rest of the current iteration. Put either control keyword inside the loop body, including within a conditional structure. They cannot be placed in a separate keyword called by the loop body.

*** Test Cases ***
Stop When Found
    @{items}=    Create List    first    target    later
    FOR    ${item}    IN    @{items}
        IF    $item == 'target'
            Log    Found target
            BREAK
        END
        Log    Still searching: ${item}
    END

Skip Empty Values
    @{items}=    Create List    alpha    ${EMPTY}    beta
    FOR    ${item}    IN    @{items}
        IF    $item == $EMPTY
            CONTINUE
        END
        Log    Processing ${item}
    END

4. When to use Repeat Keyword instead

If the goal is only to run one keyword a fixed number of times, a full loop may add unnecessary structure. Robot Framework’s BuiltIn Repeat Keyword can express that directly:

*** Test Cases ***
Retry A Simple Action
    Repeat Keyword    3 times    Log    Checking again

For a series of values, conditions, indexes, or multiple calls per pass, use a FOR loop instead. The official Robot Framework User Guide notes that test libraries can provide loop constructs and that loop logic often belongs in libraries.

5. Version and syntax notes

  • Use the block form FOR ... END in current code.
  • Nested FOR loops and the custom start= option for IN ENUMERATE are available from Robot Framework 4.0.
  • The older :FOR syntax was deprecated in Robot Framework 3.2 and removed in 4.0.
  • For exact behavior and version-specific details, consult the Robot Framework 7.4.2 User Guide, Control Structures.

6. Troubleshooting common loop errors

Symptom Likely cause Fix
Parser rejects a loop or reports an unexpected token A block is missing END, or FOR/IN casing is wrong. Use uppercase markers and close each block with its own END row.
Old loop example fails on a current Robot Framework version It uses the removed :FOR form. Rewrite it as a FOR ... IN ... END block.
Loop runs zero times or misses the expected final number IN RANGE excludes its end value. Adjust the end argument if you need that value included.
Paired data appears mismatched Lists are not aligned by position, or multiple loop variables do not divide evenly into the values. Check collection ordering and lengths; use IN ZIP for corresponding list elements.
Nested loop or custom enumerate start is rejected The Robot Framework version is older than 4.0. Upgrade to version 4.0 or later, or rewrite without the unsupported feature.
BREAK or CONTINUE is rejected The control keyword is outside a loop body or inside a called keyword. Move it into the loop’s body, optionally under an IF.
Loop body is difficult to maintain Too much branching or work is packed into the loop. Move the work into a well-named user keyword or a library keyword.

7. Performance, reliability, and cost

Choose the loop form that matches the input and avoid repeating expensive setup work inside every iteration when it can be done once before the loop. Keep iteration count bounded when deriving values from external input, and make failures identify the current item or index so a test report is actionable. The cited loop documentation provides no benchmark or cost figures, so performance depends on the keywords and systems each iteration invokes; a loop over local values is not equivalent to repeating browser or network work.

8. Capture screenshots from a Robot Framework loop

A loop can also drive repeated website captures—for example, capturing several URLs in a regression check. For a DIY browser workflow, put the browser setup and capture keywords in a user keyword, then call it once per URL. This Robot Framework example uses the Browser library keyword interface, so install and configure the library in the project before running it:

*** Settings ***
Library    Browser

*** Test Cases ***
Capture Pages
    @{urls}=    Create List    https://example.com    https://robotframework.org
    FOR    ${url}    IN    @{urls}
        New Browser    chromium    headless=True
        New Page    ${url}
        Take Screenshot    filename=${OUTPUT DIR}/${url}.png
        Close Browser
    END

When applying this pattern in a real suite, use safe filenames derived from each URL and ensure the browser is closed even if navigation or capture fails. The loop syntax itself is built into Robot Framework; browser keywords come from the configured library.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. Replace local browser lifecycle code with one request per URL. See the ScreenshotNeo API documentation for the request options.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);

ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server gives AI agents screenshot tools. The free plan includes 1,000 screenshots a month without a card; paid plans start at $5 for 3,000 screenshots.

Create a free ScreenshotNeo account for 1,000 screenshots a month, with no card required.

9. FAQ

Can a loop run in a user keyword?

Yes. The same block-loop form works in test cases and user keywords.

Does IN RANGE include its end?

No. Its end is exclusive.

Can BREAK stop only one nested loop?

Use it in the loop body whose execution you want to stop, and structure nested control flow so the intended loop is clear.

Where can I check the full supported syntax?

See the official Robot Framework User Guide control structures section.