Skip to main content

Waiting & Finding Actions

Actions for waiting for elements to appear, pages to load, or network activity to finish.

waitForElement

Wait for an element to appear in the DOM. Keeps checking until found or the timeout runs out.

Value: string (selector)

<!-- appears after the page fetches data -->
<div class="results">...</div>
[
{ "waitForElement": ".results" }
]

Wait until visible on screen:

[
{
"waitForElement": ".modal",
"options": { "visible": true, "timeout": 5000 }
}
]

Save for later use:

[
{ "waitForElement": ".result-card", "options": { "save": "card" } },
{ "click": "$card" }
]

Options

OptionTypeDefaultDescription
timeoutnumber10000How long to wait (ms)
visibleboolean | "all"falsefalse = exists anywhere in DOM, true = must be visible on screen, "all" = accept any visibility state (hidden or visible)
savestringSave the found element for later
iframestring | string[]Look inside an iframe

find

Shorthand for waitForElement. Works exactly the same way.

Value: string (selector)

[
{ "find": ".search-results" }
]

With timeout and save:

[
{
"find": "#dynamic-content",
"options": { "timeout": 15000, "save": "content" }
}
]

findByText

Find the most specific element that contains certain text. Case-insensitive.

Value: string (text to search for)

<div class="actions">
<button>Cancel</button>
<button>Submit Order</button>
</div>
[
{ "findByText": "Submit Order" }
]

Partial text match:

[
{ "findByText": "Submit", "options": { "selector": "button", "exact": false } }
]

Save for later use:

[
{ "findByText": "Sign In", "options": { "selector": "button", "save": "signInBtn" } },
{ "click": "$signInBtn" }
]

Options

OptionTypeDefaultDescription
selectorstring"*"Only search within elements matching this selector
exactbooleanfalsetrue = full text match, false = contains
savestringSave the element for later
waitForbooleantrueWait for the element to appear
timeoutnumber10000How long to wait (ms)
iframestring | string[]Look inside an iframe

findByAttribute

Find an element by one of its HTML attributes, like data-testid or aria-label.

Value: [attribute, value]

<button data-testid="submit-button">Submit</button>
[
{ "findByAttribute": ["data-testid", "submit-button"] }
]

Partial value match:

[
{ "findByAttribute": ["data-testid", "submit"], "options": { "exact": false } }
]

Save for later use:

[
{
"findByAttribute": ["aria-label", "Close dialog"],
"options": { "save": "closeBtn" }
},
{ "click": "$closeBtn" }
]

Options

OptionTypeDefaultDescription
selectorstring"*"Only search within elements matching this selector
exactbooleanfalsetrue = full value match, false = contains
savestringSave the element for later
waitForbooleantrueWait for the element to appear
timeoutnumber10000How long to wait (ms)
iframestring | string[]Look inside an iframe

waitForEvent

Wait for a browser-level page event.

Value: "load" | "networkidle"

Wait for the page and all its resources (images, scripts, stylesheets) to fully load:

[
{ "waitForEvent": "load" }
]

Wait until there are no active network requests for 500ms:

[
{ "waitForEvent": "networkidle" }
]

"networkidle" watches active network connections in the tab. Once all requests have settled and no new ones start for 500ms, it resolves. This is useful when the page visually appears loaded but is still fetching data in the background — a common pattern in:

  • Single-page apps (React, Vue, Angular) — route changes don't reload the page, so "load" never fires again after the first visit
  • Dashboards and data grids — the shell loads first, then separate API calls populate tables and charts
  • Infinite scroll — the initial batch of items loads via XHR after the page is ready
  • Search-as-you-type — waiting for results to finish loading before reading them
When to use each

Use "load" right after navigating to a new page to wait for all static assets (images, scripts, stylesheets) to finish. Use "networkidle" when content is fetched dynamically after the initial page load.

Options

OptionTypeDefaultDescription
timeoutnumber10000How long to wait (ms)

Custom timeout:

[
{ "waitForEvent": "networkidle", "options": { "timeout": 15000 } }
]

waitForResponse

Intercept a network request and capture its response. Non-blocking — starts listening immediately and returns the captured response at the end of the task. Matches the URL by substring or regex.

Value: string (URL substring or regex pattern)

[
{ "waitForResponse": "/api/products" }
]

Filter by HTTP method:

[
{ "waitForResponse": "/api/search", "options": { "method": "GET" } }
]

Returns: The response body, parsed as JSON if possible.

Set up the listener first, then trigger the action that causes the request:

[
{ "open": "https://example.com/search" },
{ "waitForResponse": "/api/search" },
{ "fill": ["input#search", "laptop"] },
{ "click": "#search-btn" }
]

The response data is returned in the task result. If you also need to interact with the rendered results, add waitForElement after the click.

Options

OptionTypeDefaultDescription
methodstringOnly match a specific HTTP method: "GET", "POST", etc.
timeoutnumber10000How long to wait (ms)
Unsupported inside loop and if

waitForResponse cannot be used inside loop or if branches.


Example: Wait for Page Data to Load

[
{ "openNewTab": "https://example.com/dashboard" },
{ "waitForEvent": "networkidle" },
{ "waitForElement": ".data-table", "options": { "visible": true } },
{ "screenshot": "viewport" }
]

Example: Capture an API Response

[
{ "openNewTab": "https://example.com/search" },
{ "waitForResponse": "/api/search", "options": { "method": "GET" } },
{ "fill": ["input#search", "laptop"] },
{ "click": "#search-btn" }
]