CDP Use

repository·main·Indexed 43 days ago

https://github.com/browser-use/cdp-use

A type-safe Python client generator for the Chrome DevTools Protocol (CDP) version 1.4.5. It automatically generates Python bindings using TypedDict from official CDP specifications to provide IntelliSense and compile-time error checking for browser automation. The library features a CDPClient for WebSocket connections, a CDPLibrary for sending type-safe commands, and a CDPRegistrationLibrary for managing event handlers.

Tokens
2.3K
Snippets
10
Records
11
Agent score
56%

What's inside CDP Use

  1. How CDPClient, CDPLibrary, and CDPRegistrationLibrary work together

    main

    The library is structured around three main components that compose the client interface:

    1. CDPClient: The entry point. It holds the WebSocket connection and provides two main interfaces: .send for commands and .register for events.
    2. CDPLibrary: Accessed via client.send. It is a collection of domain-specific clients (e.g., DOMClient, NetworkClient, RuntimeClient). Each domain client provides methods to send CDP commands.
    3. CDPRegistrationLibrary: Accessed via client.register. It provides domain-specific registration interfaces (e.g., PageRegistration, RuntimeRegistration) to attach event handlers.

    This separation ensures that command execution and event subscription are logically organized by CDP domain.

  2. Basic usage of CDPClient

    main

    Use CDPClient as an asynchronous context manager to connect to a Chrome DevTools WebSocket URL. You can send commands via the .send attribute, which provides access to various CDP domains (e.g., Target, Page).

    Example of connecting and navigating:

    import asyncio
    from cdp_use.client import CDPClient
    
    async def main():
        # Connect to Chrome DevTools
        async with CDPClient("ws://localhost:9222/devtools/browser/...") as cdp:
            # Get all browser targets
            targets = await cdp.send.Target.getTargets()
            print(f"Found {len(targets['targetInfos'])} targets")
    
            # Navigate to a page
            await cdp.send.Page.navigate({"url": "https://example.com"})
    
    asyncio.run(main())
    import asyncio
    from cdp_use.client import CDPClient
    
    async def main():
        async with CDPClient("ws://localhost:9222/devtools/browser/...") as cdp:
            targets = await cdp.send.Target.getTargets()
            await cdp.send.Page.navigate({"url": "https://example.com"})
    
    asyncio.run(main())
  3. Install and setup CDP Use

    main

    To use cdp-use, you must first clone the repository, install dependencies using uv or pip, and then run the generator to create the type-safe Python bindings from the official Chrome DevTools Protocol specifications.

    1. Clone and install dependencies:
    git clone https://github.com/browser-use/cdp-use
    cd cdp-use
    uv sync  # or pip install -r requirements.txt
    1. Generate the CDP client library:
    python -m cdp_use.generator
    git clone https://github.com/browser-use/cdp-use
    cd cdp-use
    uv sync
    python -m cdp_use.generator
  4. Regenerate CDP types from protocol specifications

    main

    If you need to update the library to use a different version of the Chrome DevTools Protocol, you can regenerate the bindings.

    To use the latest version from the master branch, run:

    python -m cdp_use.generator

    To pin a specific version, edit cdp_use/generator/constants.py and set the CDP_VERSION variable to a specific commit hash from the official devtools-protocol repository.

    Example pinning:

    # In cdp_use/generator/constants.py
    CDP_VERSION = "4b0c3f2e8c5d6a7b9e1f2a3c4d5e6f7a8b9c0d1e"
  5. Register type-safe event handlers

    main

    The library allows you to register event handlers using the .register attribute. Event names follow the camelCase convention used in the CDP specification.

    Syntax: client.register.Domain.eventName(callback_function)

    Requirements for callback_function:

    • It must accept two parameters: (event_data, session_id).
    • event_data is a TypedDict representing the event payload.
    • session_id is an Optional[str].

    Important: You must call .enable() on the relevant domain (e.g., await client.send.Page.enable()) to start receiving events.

    Example:

    import asyncio
    from cdp_use.client import CDPClient
    from cdp_use.cdp.page.events import FrameAttachedEvent, DomContentEventFiredEvent
    from cdp_use.cdp.runtime.events import ConsoleAPICalledEvent
    from typing import Optional
    
    def on_frame_attached(event: FrameAttachedEvent, session_id: Optional[str]) -> None:
        print(f"Frame {event['frameId']} attached")
    
    def on_console_message(event: ConsoleAPICalledEvent, session_id: Optional[str]) -> None:
        print(f"Console: {event['type']}")
    
    async def main():
        async with CDPClient("ws://localhost:9222/devtools/page/...") as client:
            # Register handlers
            client.register.Page.frameAttached(on_frame_attached)
            client.register.Runtime.consoleAPICalled(on_console_message)
    
            # Enable domains
            await client.send.Page.enable()
            await client.send.Runtime.enable()
    
            await client.send.Page.navigate({"url": "https://example.com"})
            await asyncio.sleep(5)
    
    asyncio.run(main())
    client.register.Page.frameAttached(on_frame_attached)
    await client.send.Page.enable()
  6. Send type-safe CDP commands with client.send

    main

    The client.send attribute provides access to the CDPLibrary, which contains type-safe wrappers for Chrome DevTools Protocol commands. Instead of sending raw JSON, you use these methods to ensure parameters and return types are correctly handled.

    While send_raw is available for arbitrary method calls, it is recommended to use the send library for full type safety and IDE autocompletion.

    # Using the type-safe library (example pattern)
    # Note: Actual method names depend on the CDPLibrary implementation
    result = await client.send.Page.navigate({"url": "https://example.com"})
  7. Send raw CDP commands with send_raw

    main

    If you need to call a CDP method that is not yet covered by the type-safe CDPLibrary, use send_raw. This method sends a JSON-RPC request and waits for the response.

    • method: The string name of the CDP method (e.g., Runtime.evaluate).
    • params: A dictionary of arguments for the method.
    • session_id: (Optional) The ID of the specific browser target session to use.
    # Sending a raw command
    result = await client.send_raw(
        method="Runtime.evaluate",
        params={"expression": "1 + 1"}
    )
  8. Register and handle CDP events

    main

    To react to asynchronous browser events (like Page.loadEventFired), use the client.register attribute, which provides access to the CDPRegistrationLibrary. This allows you to attach handlers to specific CDP methods that the browser emits.

    Events are managed by an internal EventRegistry that routes incoming messages to your registered callbacks based on the method name.

    # Example pattern for registering an event handler
    @client.register.Page.loadEventFired
    async def on_page_load(params):
        print(f"Page loaded: {params}")
  9. Use the CDPClient class

    main

    The CDPClient class is the primary entrypoint for interacting with Chrome DevTools Protocol (CDP) via the cdp-use library. It provides high-level, type-safe methods for browser automation, including connecting to existing Chrome instances, navigating pages, and managing browser targets.

    from cdp_use import CDPClient
    
    # Example initialization (actual connection logic depends on CDPClient implementation)
    client = CDPClient(...)
  10. Initialize and manage a CDPClient

    main

    The CDPClient is the primary entry point for interacting with Chrome DevTools via the WebSocket protocol. It provides a type-safe interface for sending commands and handling browser events. You can manage the client lifecycle using an async context manager, which automatically handles connection startup and teardown.

    Key Configuration Options

    • url: The WebSocket endpoint (e.g., ws://localhost:9222/devtools/browser/...).
    • additional_headers: An optional dictionary of HTTP headers to include in the WebSocket handshake.
    • max_ws_frame_size: The maximum allowed size for a single WebSocket frame (defaults to 100MB).
    from cdp_use.client import CDPClient
    
    async def main():
        url = "ws://localhost:9222/devtools/browser/your-id"
        async with CDPClient(url=url) as client:
            # Your CDP logic here
            pass
    
    import asyncio
    asyncio.run(main())
  11. Emit custom synthetic events

    main

    The emit_event method allows you to manually trigger events through the client's internal EventRegistry. This is particularly useful for custom domains or application-level events that are not part of the standard Chrome DevTools Protocol but need to be processed by the same event-handling logic used by the browser.

    # Manually trigger an event that registered handlers will catch
    await client.emit_event("MyCustomDomain.event", {"data": "value"})