# How to Wait for Elements with a Specific Timeout in Zendriver

> Learn how to wait for elements with a specific timeout in Zendriver using Tab.wait_for, Tab.select, or Tab.select_all. Avoid issues by setting custom timeouts for element polling.

- Repository: [CDP Driver/zendriver](https://github.com/cdpdriver/zendriver)
- Tags: how-to-guide
- Published: 2026-02-27

---

**Use `Tab.wait_for()`, `Tab.select()`, or `Tab.select_all()` with the `timeout` parameter (in seconds) to poll for DOM elements; these methods raise `asyncio.TimeoutError` if the element doesn't appear within the specified window.**

Zendriver (cdpdriver/zendriver) is an async Python library that controls Chrome via the Chrome DevTools Protocol (CDP). When automating dynamic web pages, you need reliable ways to wait for elements to appear before interacting with them. The library provides several timeout-aware polling methods that handle this without busy-waiting.

## Understanding Zendriver's Timeout-Based Waiting Mechanism

All waiting methods in Zendriver follow the same asynchronous polling pattern implemented in [`zendriver/core/tab.py`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/tab.py). The mechanism works by:

1. **Starting a timer** using `asyncio.get_running_loop().time()` to track elapsed time.
2. **Polling the DOM** via `query_selector`, `find_element_by_text`, or similar selectors in a loop.
3. **Sleeping briefly** between attempts using `await self.sleep(0.5)` (defined in [`zendriver/core/util.py`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/util.py), lines 258-270) to avoid blocking the event loop.
4. **Raising `asyncio.TimeoutError`** when the elapsed time exceeds the user-supplied `timeout` argument (in seconds).

This approach ensures that your automation script waits efficiently without consuming excessive CPU, while still providing precise control over how long to wait before failing.

## Waiting for a Single Element by CSS Selector

### Using `wait_for()` with Selectors

The primary method for waiting with a specific timeout is `Tab.wait_for()` (implemented in [`zendriver/core/tab.py`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/tab.py), lines 1116-1156). This method accepts either a CSS selector or visible text and polls until the element appears or the timeout expires.

```python
import asyncio
import zendriver as zd

async def main():
    browser = await zd.start()
    tab = await browser.get("https://example.com")
    
    try:
        # Wait up to 5 seconds for the submit button

        element = await tab.wait_for(selector="button.submit", timeout=5)
        await element.click()
    except asyncio.TimeoutError:
        print("Submit button did not appear within 5 seconds")
    finally:
        await browser.stop()

if __name__ == "__main__":
    asyncio.run(main())

```

### Using the `select()` Convenience Method

For CSS selectors specifically, `Tab.select()` (lines 1248-1275 in [`zendriver/core/tab.py`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/tab.py)) provides a dedicated wrapper around `query_selector` with the same timeout logic. This method is slightly more concise when you only need CSS selection.

```python
try:
    # Wait up to 3 seconds for the search input

    search_box = await tab.select("input[name='q']", timeout=3)
    await search_box.type("zendriver tutorial")
except asyncio.TimeoutError:
    print("Search box not found within 3 seconds")

```

## Waiting for Elements by Visible Text

When you need to locate an element by its visible text content rather than a CSS selector, use the `text` parameter of `Tab.wait_for()`. Internally, this invokes `find_element_by_text()` (implemented in [`zendriver/core/tab.py`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/tab.py), lines 627-665), which searches the DOM for elements matching the specified text pattern.

```python
try:
    # Wait up to 8 seconds for the welcome message

    welcome_banner = await tab.wait_for(text="Welcome back", timeout=8.0)
    print("Found the welcome banner")
except asyncio.TimeoutError:
    print("Welcome banner never showed up")

```

This approach is particularly useful for dynamic content where CSS classes may change frequently but the text content remains stable.

## Waiting for Multiple Elements

To wait for multiple elements matching a CSS selector (rather than just the first one), use `Tab.select_all()` (lines 1306-1342 in [`zendriver/core/tab.py`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/tab.py)). This method returns a list of all matching elements once at least one is found, or raises `asyncio.TimeoutError` if none appear within the specified window.

```python
try:
    # Wait up to 4 seconds for article posts to load

    posts = await tab.select_all("article.post", timeout=4, include_frames=False)
    print(f"Found {len(posts)} posts")
    
    for post in posts:
        title = await post.query_selector("h2")
        if title:
            print(await title.get_text())
except asyncio.TimeoutError:
    print("No posts appeared within 4 seconds")

```

The `include_frames` parameter controls whether the search should extend into iframe contexts.

## Waiting for Page Ready State

Before interacting with elements, you may need to ensure the page has reached a specific loading state. `Tab.wait_for_ready_state()` (lines 1158-1185 in [`zendriver/core/tab.py`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/tab.py)) polls the document's `readyState` property until it matches the desired value (`interactive` or `complete`).

```python
await tab.get("https://example.com")
await tab.wait_for_ready_state("complete", timeout=12)
print("Page fully loaded and ready for interaction")

```

This method is essential for single-page applications (SPAs) where the initial DOM load completes quickly but dynamic content continues loading via JavaScript.

## Handling Timeout Errors

All waiting methods in Zendriver raise `asyncio.TimeoutError` when the specified timeout expires before the condition is met. This standard Python exception allows you to implement fallback logic or graceful degradation in your automation scripts.

```python
import asyncio

async def safe_click(tab, selector, timeout=5):
    try:
        element = await tab.wait_for(selector=selector, timeout=timeout)
        await element.click()
        return True
    except asyncio.TimeoutError:
        print(f"Element {selector} not found within {timeout}s, skipping")
        return False

```

Always wrap waiting calls in try-except blocks when the element's presence is uncertain or when dealing with flaky network conditions.

## Summary

- **Use `Tab.wait_for()`** (lines 1116-1156 in [`zendriver/core/tab.py`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/tab.py)) for flexible waiting by CSS selector or visible text with a specific timeout.
- **Use `Tab.select()`** (lines 1248-1275) for CSS-only single element waiting, and **`Tab.select_all()`** (lines 1306-1342) for multiple elements.
- **All methods accept a `timeout` parameter** in seconds (int or float) and poll every 0.5 seconds until the element appears.
- **Handle `asyncio.TimeoutError`** to manage cases where elements fail to appear within the specified window.
- **Use `Tab.wait_for_ready_state()`** (lines 1158-1185) to ensure page load completion before element interaction.

## Frequently Asked Questions

### What exception does Zendriver raise when a timeout expires?

Zendriver raises the standard **`asyncio.TimeoutError`** when the specified timeout is reached before the element appears. This allows you to catch the exception using Python's standard asyncio error handling patterns and implement fallback logic or retry mechanisms as needed.

### How often does Zendriver poll the DOM when waiting for an element?

According to the implementation in [`zendriver/core/tab.py`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/tab.py), Zendriver polls the DOM every **0.5 seconds** during the wait loop. This interval is hardcoded in the `sleep(0.5)` calls within methods like `wait_for`, `select`, and `select_all`, balancing responsiveness with CPU efficiency.

### Can I wait for an element to appear by its visible text instead of a CSS selector?

Yes. Use the **`text`** parameter of `Tab.wait_for()` to search for elements by their visible text content. Internally, this invokes `find_element_by_text()` (lines 627-665 in [`zendriver/core/tab.py`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/tab.py)), which traverses the DOM looking for text matches. You can combine this with the `timeout` parameter to limit how long the search continues.

### What is the difference between `wait_for()` and `select()` in Zendriver?

**`wait_for()`** is the generic waiting method that accepts either a `selector` (CSS) or `text` parameter, making it flexible for different identification strategies. **`select()`** is a convenience method specifically optimized for CSS selectors only (lines 1248-1275), providing a slightly cleaner API when you only need to wait for a CSS-matched element. Both methods implement identical timeout and polling logic internally.