cdp-use-rs 0.1.1

Type-safe Chrome DevTools Protocol client for Rust with auto-generated bindings from official CDP specs
Documentation
# CDP Use (Rust)

Rust implementation of [cdp-use](https://github.com/browser-use/cdp-use) -- a **type-safe Chrome DevTools Protocol client** with auto-generated bindings from the official CDP protocol specifications.

## Features

- **Type-safe commands & events** -- Strongly typed structs for all 53 CDP domains, generated at build time via `build.rs`
- **Async WebSocket client** -- Built on `tokio` + `tokio-tungstenite` with proper timeout, close ordering, and concurrent event dispatch
- **Typed event registration** -- Register async closures for CDP events with full type safety
- **Configurable connection** -- Custom WebSocket frame size, headers, and command timeout via `CdpClientConfig`
- **Zero manual maintenance** -- Code generated directly from `browser_protocol.json` and `js_protocol.json`

## Installation

Add to your `Cargo.toml`:

```toml
[dependencies]
cdp-use-rs = "0.1"

# or from git
cdp-use-rs = { git = "https://github.com/netkn001/cdp-use-rs" }
```

## Quick Start

```rust
use cdp_use::page;

#[tokio::main]
async fn main() -> Result<(), cdp_use::CdpError> {
    // Connect to Chrome running with --remote-debugging-port=9222
    let cdp = cdp_use::CdpClient::connect("ws://127.0.0.1:9222/devtools/browser/...").await?;

    let send = cdp.send();
    let register = cdp.register();

    // List targets
    let targets = send.target.get_targets(Default::default(), None).await?;
    println!("Found {} targets", targets.target_infos.len());

    // Attach to a page target
    let page_target = targets.target_infos.iter()
        .find(|t| t.r#type == "page")
        .expect("No page target");

    let session = send.target.attach_to_target(
        cdp_use::target::commands::AttachToTargetParams {
            target_id: page_target.target_id.clone(),
            flatten: Some(true),
            ..Default::default()
        },
        None,
    ).await?;
    let sid = session.session_id;

    // Enable Page domain and register event handler
    send.page.enable(Default::default(), Some(&sid)).await?;

    register.page.frame_navigated(|event, _session_id| async move {
        println!("Navigated: {} -> {}", event.frame.id, event.frame.url);
    });

    // Navigate
    let nav = send.page.navigate(
        page::commands::NavigateParams {
            url: "https://example.com".into(),
            ..Default::default()
        },
        Some(&sid),
    ).await?;
    println!("Frame: {}", nav.frame_id);

    cdp.close().await?;
    Ok(())
}
```

## Custom Configuration

```rust
use cdp_use::{CdpClient, CdpClientConfig};
use std::time::Duration;

let config = CdpClientConfig {
    max_message_size: Some(100 * 1024 * 1024), // 100 MiB (default)
    max_frame_size: Some(16 * 1024 * 1024),    // 16 MiB
    command_timeout: Duration::from_secs(60),    // default: 30s
    additional_headers: [("Authorization".into(), "Bearer token".into())].into(),
};

let cdp = CdpClient::connect_with_config("ws://...", config).await?;
```

## Architecture

```
cdp-use-rs/
  build.rs              # Code generator -- reads protocol JSON, emits generated.rs
  protocols/
    browser_protocol.json
    js_protocol.json
  src/
    lib.rs              # Public API re-exports
    client.rs           # WebSocket client, event registry, CdpClientConfig
    error.rs            # CdpError enum
  examples/
    basic.rs            # Full usage example
  tests/
    codegen_test.rs     # Type/serialization/config tests
    integration_test.rs # Live browser integration tests
```

At build time, `build.rs` parses the CDP protocol JSON files and generates a `generated.rs` containing:

- **Types** -- Structs, enums, and type aliases for each domain (`page::types::Frame`, `network::types::RequestId`, ...)
- **Commands** -- `*Params` / `*Returns` structs and typed async methods on domain clients
- **Events** -- Event structs and typed registration methods
- **CdpLibrary / CdpRegistrationLibrary** -- Top-level accessors: `cdp.send().page.navigate(...)`, `cdp.register().page.frame_navigated(...)`

## Comparison with Other Browser Automation Tools

| | Selenium | Puppeteer | Playwright | cdp-use (Python) | **cdp-use-rs** |
|---|---|---|---|---|---|
| **Language** | Java, Python, C#, JS, Ruby | Node.js | Node.js, Python, Java, .NET | Python | **Rust** |
| **Protocol** | WebDriver (W3C) | CDP | CDP + custom protocol | CDP (raw) | **CDP (raw)** |
| **Browser support** | Chrome, Firefox, Safari, Edge | Chrome, Firefox (experimental) | Chrome, Firefox, WebKit | Chrome (any CDP target) | **Chrome (any CDP target)** |
| **Abstraction level** | High-level | High-level | High-level | Low-level (1:1 CDP mapping) | **Low-level (1:1 CDP mapping)** |
| **Type safety** | Varies by language | TypeScript types | TypeScript types | TypedDict + Literal | **Structs + enums + serde** |
| **Auto-wait / retries** | Implicit/explicit waits | Built-in auto-wait | Built-in auto-wait | None (manual) | **None (manual)** |
| **Selectors** | CSS, XPath | CSS, XPath, aria | CSS, XPath, text, role, test-id | N/A (raw CDP) | **N/A (raw CDP)** |
| **Code generation** | N/A | N/A | `codegen` CLI | Runtime script | **Build-time `build.rs`** |
| **CDP domain coverage** | Partial (abstracted away) | Partial (high-level API) | Partial (high-level API) | Full 53 domains | **Full 53 domains** |
| **Use case** | Cross-browser E2E testing | Chrome automation & scraping | Cross-browser E2E testing | Full CDP control, AI agent infra | **Full CDP control, AI agent infra** |

### When to use cdp-use-rs

- You need **direct access to all 53 CDP domains** without abstraction layers getting in the way
- You're building **AI browser agents** or infrastructure that requires low-level protocol control
- You want **compile-time type safety** and **zero-cost abstractions** over the CDP protocol
- Performance matters -- Rust's async runtime and zero-overhead WebSocket handling
- You're integrating CDP into a larger Rust system (e.g., an agent framework, a proxy, or a custom browser controller)

### When to use Playwright / Puppeteer / Selenium instead

- You need **cross-browser support** (Firefox, WebKit/Safari)
- You want **high-level APIs** with built-in auto-wait, selectors, and test assertions
- You're writing **E2E tests** for web applications
- You prefer a batteries-included approach with screenshots, tracing, and network interception out of the box

## Comparison with Python cdp-use

| | Python (cdp-use) | Rust (cdp-use-rs) |
|---|---|---|
| **Domains** | 53 | 53 |
| **Type system** | `TypedDict` + `Literal` | Structs + enums with serde |
| **Optional fields** | `NotRequired[T]` | `Option<T>` + `skip_serializing_if` |
| **Naming** | camelCase (JS convention) | snake_case + `#[serde(rename_all = "camelCase")]` |
| **Async runtime** | asyncio | tokio |
| **WebSocket** | websockets | tokio-tungstenite |
| **Code generation** | Runtime script | Build-time `build.rs` |
| **Event handlers** | Sync or async callbacks | Async closures (spawned per event) |

## Development

```bash
cargo build    # Generates CDP bindings and compiles
cargo test     # Run all tests
cargo doc      # Generate documentation

# Run the example (requires Chrome with --remote-debugging-port=9222)
cargo run --example basic -- "ws://127.0.0.1:9222/devtools/browser/GUID"
```

## Related

- [cdp-use]https://github.com/browser-use/cdp-use -- Original Python implementation
- [Chrome DevTools Protocol]https://chromedevtools.github.io/devtools-protocol/ -- Official protocol documentation
- [browser-use]https://github.com/browser-use/browser-use -- Browser automation framework

## License

MIT