# How to Use CDP Commands Directly in ego-browser with the cdp Helper

> Learn how to use CDP commands directly in ego-browser with the cdp helper. Send raw Chrome DevTools Protocol commands from agent scripts effortlessly.

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

---

**The `cdp` helper in ego-browser lets you send raw Chrome DevTools Protocol commands from agent scripts by calling `await cdp(method, params?, sessionId?)` without any import statements.**

The `ego-browser` package from the `citrolabs/ego-lite` repository exposes a low-level `cdp` helper that bridges the gap between high-level automation APIs and the raw Chrome DevTools Protocol (CDP). This helper is injected directly into the global scope of agent scripts, allowing you to execute arbitrary CDP commands against the underlying browser instance. Whether you need to navigate pages, evaluate scripts, or manipulate network interception, the `cdp` helper provides direct access to the browser's debugging protocol.

## What Is the cdp Helper?

The `cdp` helper is a thin wrapper around the runtime's CDP transport layer, defined in [[`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/cdp-eval.ts). It routes commands through the shared state—checking for `state.cdpOverride` first, then falling back to the default `send` implementation—while maintaining internal bookkeeping for Network domain events.

According to the source code, the helper is re-exported from [[`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) and documented in the public API signature within [[`src/format.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/format.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts). This ensures that when you call `cdp` in your scripts, you're invoking a managed transport that properly tracks `networkDomainEnabled` states in [[`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/state.ts).

## How the cdp Helper Works

When you invoke `await cdp(method, params?, sessionId?)`, the execution flow follows this path:

1. **Command Routing**: The call checks `state.cdpOverride` for custom transport handling or uses the default `send` implementation.
2. **Network Bookkeeping**: If the command relates to the Network domain (e.g., `Network.enable`), the helper updates internal flags in the shared state to ensure higher-level helpers like `waitForNetworkIdle` remain synchronized.
3. **Session Targeting**: The optional `sessionId` parameter routes the command to specific targets, such as child iframes or separate browser contexts.

This architecture ensures that direct CDP usage doesn't break the agent's internal consistency, particularly for network monitoring features implemented in [[`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/waits.ts).

## Using the cdp Helper in Agent Scripts

### Basic Syntax

All helpers are automatically injected into your script's global scope by the runtime. You call `cdp` without import statements using the signature:

```javascript
await cdp(method, params?, sessionId?)

```

- **method**: String matching the CDP domain and command (e.g., `"Page.navigate"`, `"Runtime.evaluate"`)
- **params**: Object containing the method's required parameters
- **sessionId**: Optional string for targeting specific sessions

### Practical Examples

**Navigate to a URL and wait for load:**

```javascript
// Navigate using CDP directly
await cdp('Page.navigate', { url: 'https://example.com' });

// Wait for the load event
await cdp('Page.loadEventFired');

```

**Evaluate JavaScript in the page context:**

```javascript
const result = await cdp('Runtime.evaluate', {
  expression: 'document.title',
  returnByValue: true,
});

console.log('Page title:', result.result?.value);

```

**Enable network monitoring and capture responses:**

```javascript
// Enable network domain
await cdp('Network.enable');

// Disable caching
await cdp('Network.setCacheDisabled', { cacheDisabled: true });

// Wait for specific response and get body
const response = await cdp('Network.responseReceived', { requestId: '123.1' });
const body = await cdp('Network.getResponseBody', { 
  requestId: response.response?.requestId 
});

console.log('Response body:', body.body);

```

## Advanced Session Targeting

The `cdp` helper supports targeting specific browser sessions, enabling you to interact with child iframes or separate targets. This pattern is demonstrated in navigation utilities found in [[`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/nav.ts).

**Attach to a specific target and execute commands:**

```javascript
// Attach to a frame or service worker
const { sessionId } = await cdp('Target.attachToTarget', {
  targetId: 'iframe-target-id',
  flatten: true,
});

// Execute in that specific context
const href = await cdp(
  'Runtime.evaluate', 
  { expression: 'window.location.href' }, 
  sessionId
);

console.log('Frame URL:', href.result?.value);

```

The `flatten: true` parameter creates a flat session hierarchy compatible with modern Chrome versions, returning a `sessionId` that you pass as the third argument to subsequent `cdp` calls.

## Summary

- The **`cdp` helper** provides direct access to Chrome DevTools Protocol commands within `ego-browser` agent scripts.
- Implementation resides in **[`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts)**, with exports managed through **[`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts)** and state tracking in **[`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts)**.
- **Global scope injection** means no imports are required; call `cdp(method, params?, sessionId?)` directly.
- **Network domain integration** ensures that enabling `Network` commands via CDP doesn't break `waitForNetworkIdle` and other high-level helpers.
- **Session targeting** via the optional `sessionId` parameter allows precise control over iframes and isolated browser contexts.

## Frequently Asked Questions

### Do I need to import the cdp helper in my ego-browser scripts?

No. The `cdp` helper is automatically injected into the global scope by the runtime environment along with other helpers. According to the implementation in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts), you can call `cdp` directly without any import statements, as the runtime pre-binds these utilities before script execution.

### How does using the cdp helper affect waitForNetworkIdle and other high-level helpers?

The `cdp` helper in [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts) maintains internal bookkeeping for the Network domain. When you execute `Network.enable` or related commands through `cdp`, it updates the `networkDomainEnabled` flag in the shared state (defined in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts)). This synchronization ensures that utilities like `waitForNetworkIdle` in [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) continue to function correctly alongside your raw CDP commands.

### Can I use the cdp helper to interact with iframes or web workers?

Yes. Pass the `sessionId` as the third argument to target specific contexts. First attach to the target using `Target.attachToTarget` with `flatten: true`, which returns a session ID, then use that ID in subsequent `cdp` calls to execute commands within that specific frame, web worker, or service worker context.

### What happens if a CDP command doesn't return a payload?

The `cdp` helper returns a Promise that resolves to the raw CDP response object. If the underlying transport does not return a payload (common with event-based commands like `Page.loadEventFired`), the helper resolves to an empty object `{}`. Always check the response structure or use optional chaining when accessing nested result properties.