# How to Wait for Specific Browser Events in ego-lite: A Complete Guide

> Learn how to wait for specific browser events in ego-lite using waitForBrowserEvent or specialized helpers like waitForRequest and waitForResponse. Master efficient browser automation.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: how-to-guide
- Published: 2026-08-26

---

**To wait for specific browser events in ego-lite, use the `waitForBrowserEvent` function from [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) for low-level CDP events, or use specialized helpers like `waitForRequest`, `waitForResponse`, and `waitForSelector` from [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) for common automation patterns.**

Waiting for specific browser events in **citrolabs/ego-lite** ensures your automation scripts synchronize correctly with page navigation, network requests, and DOM mutations. The library implements a two-tiered waiting architecture: a low-level primitive that listens to Chrome DevTools Protocol (CDP) events directly, and a suite of high-level helpers that handle common scenarios with automatic timeout management based on values stored in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts).

## Core Event-Waiting Architecture

ego-lite structures its waiting capabilities across two primary files. The foundation resides in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts), which exports `waitForBrowserEvent`. This function registers a one-time promise that resolves when an incoming CDP event satisfies your predicate function, or rejects after the default timeout period.

Built atop this primitive, [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) provides domain-specific wrappers that abstract away protocol details:

- **`waitForRequest`** and **`waitForResponse`** – Monitor network activity using URL strings, globs, RegExp patterns, or synchronous predicates.
- **`waitForLoadState`** – Pause execution until the page reaches `load`, `domcontentloaded`, or `networkidle` states.
- **`waitForSelector`** – Poll the DOM until an element matching a CSS selector appears (optionally checking visibility).
- **`waitForNetworkIdle`** – Wait for a configurable period of network inactivity.

## Using the Low-Level `waitForBrowserEvent` Helper

For CDP events not covered by high-level helpers—such as console messages, dialog openings, or custom Page events—call `waitForBrowserEvent` directly. The helper accepts a predicate function that inspects the event object (containing `method`, `params`, `sessionId`, etc.) and returns `true` when the desired event occurs.

The function signature resolves with the full event payload, allowing you to extract any fields from the CDP response.

### Example: Waiting for Page Navigation

```javascript
// Wait until the browser emits a "Page.frameNavigated" event.
const navEvent = await waitForBrowserEvent(
  (e) => e.method === "Page.frameNavigated",
  5000   // optional timeout in ms
);
console.log('Navigated to:', navEvent.params?.url);

```

### Example: Listening for Console Messages

```javascript
const consoleMsg = await waitForBrowserEvent(
  (e) => e.method === 'Runtime.consoleAPICalled' &&
        e.params?.type === 'log' &&
        e.params?.args?.some(arg => arg.value?.includes('Ready')),
  8000
);
console.log('Console logged "Ready":', consoleMsg);

```

## High-Level Wait Helpers for Common Scenarios

When working with network activity or DOM elements, the specialized helpers in [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) provide type-safe, ergonomic alternatives to manual predicate construction.

### Waiting for Network Requests and Responses

Use **`waitForRequest`** to pause execution until a matching request initiates, or **`waitForResponse`** to wait until a response completes. Both accept URL patterns, glob strings, regular expressions, or predicate functions.

```javascript
// Wait for any request whose URL ends with ".png".
const request = await waitForRequest('**/*.png');
console.log('PNG request URL:', request.url());

// Wait for a 200 OK response using a predicate.
const response = await waitForResponse((resp) => resp.status() === 200);
console.log('Successful response URL:', response.url());

```

### Waiting for Page Load States

The **`waitForLoadState`** helper monitors page lifecycle events. Valid states include `"load"` (default), `"domcontentloaded"`, and `"networkidle"`.

```javascript
const idle = await waitForLoadState('networkidle', { idleMs: 500 });
if (idle) console.log('Network is idle');

```

### Waiting for DOM Elements

Use **`waitForSelector`** to poll for element existence or visibility. The optional `state` parameter accepts `"visible"`, `"hidden"`, or `"detached"`.

```javascript
const found = await waitForSelector('#submit-button', { state: 'visible' });
if (found) console.log('Submit button is ready');

```

### Waiting for Network Idle

The **`waitForNetworkIdle`** helper specifically monitors network activity, resolving when no requests have occurred for a specified duration (defaulting to the global timeout configuration).

## Configuration and Timeout Behavior

All wait helpers in ego-lite respect a default timeout value stored in the global state object defined in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts) (`state.defaultTimeout`). When calling any wait function, you can override this default by passing a timeout value in milliseconds as the final argument, as demonstrated in the `waitForBrowserEvent` examples above.

If the specified event does not occur within the timeout window, the promise rejects with a timeout error, enabling you to handle stalled page loads or missing elements gracefully.

## Summary

- **`waitForBrowserEvent`** in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) provides the low-level mechanism for listening to any CDP event using custom predicates.
- **High-level helpers** in [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) (`waitForRequest`, `waitForResponse`, `waitForLoadState`, `waitForSelector`) abstract common waiting scenarios with built-in polling and timeout logic.
- All helpers resolve with event payloads or element handles, allowing immediate access to event data or DOM interaction.
- Default timeouts are managed centrally in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts) but can be overridden per-call.
- These functions are injected into the script execution scope, allowing direct invocation without explicit imports.

## Frequently Asked Questions

### How does `waitForBrowserEvent` work internally?

According to the [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) source, `waitForBrowserEvent` registers a transient event listener on the CDP transport that checks each incoming event against your predicate function. Once the predicate returns `true`, the listener removes itself and resolves the promise with the full event object. If the predicate never returns `true` before the timeout expires, the promise rejects.

### What is the default timeout for wait helpers in ego-lite?

The default timeout is retrieved from `state.defaultTimeout` as defined in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts). This global configuration applies to all wait helpers including `waitForBrowserEvent`, `waitForSelector`, and network-related waits. You can override this value for individual calls by passing a millisecond value as the final argument to any wait function.

### Can I wait for custom CDP events not covered by high-level helpers?

Yes. For any CDP event not handled by `waitForRequest`, `waitForResponse`, or `waitForSelector`, call `waitForBrowserEvent` directly from [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts). Pass a predicate function that inspects the event's `method` and `params` properties to identify your target event, such as `Page.javascriptDialogOpening` for alert dialogs or `Runtime.exceptionThrown` for uncaught exceptions.

### How do I handle multiple concurrent browser events?

While `waitForBrowserEvent` and its high-level counterparts wait for a single event occurrence, you can issue multiple wait calls concurrently using `Promise.all()` or similar patterns. For example, you can simultaneously wait for a network response and a DOM element to appear, proceeding only when both conditions are satisfied.