Browser Control

The cdp.browser_control module provides a high-level browser automation API built on top of the raw CDP domain modules and CDPConnection. It offers a set of coroutines similar to what Playwright or Puppeteer expose, without requiring an external automation framework.

Note

This module requires the websockets dependency. Install it with:

pip install chrome-devtools-protocol[io]

Quick Start

import asyncio
from cdp.connection import CDPConnection
from cdp import browser_control as bc
from cdp import page

async def main():
    async with CDPConnection("ws://localhost:9222/devtools/page/ID") as conn:
        # Enable page events (required for wait_for_load)
        await conn.execute(page.enable())

        # Navigate and wait for the page to load
        await bc.navigate(conn, "https://example.com")
        await bc.wait_for_load(conn)

        # Read the heading text
        text = await bc.get_text(conn, "h1")
        print(f"Heading: {text}")

        # Click a link
        await bc.click(conn, "a")

        # Fill a form
        await bc.clear_and_type(conn, "input[name='q']", "hello world")
        await bc.press_key(conn, "Enter")

        # Capture a screenshot
        png_bytes = await bc.screenshot(conn)
        with open("page.png", "wb") as f:
            f.write(png_bytes)

asyncio.run(main())

Element Selection

Element Interaction

Element Inspection

Screenshots

JavaScript

Waiting

Patterns and Recipes

Waiting for an element before interacting

node = await bc.wait_for_selector(conn, "#submit-button", timeout=10)
await bc.click(conn, node)

Checking visibility before clicking

if await bc.is_visible(conn, ".cookie-banner"):
    await bc.click(conn, ".cookie-banner .dismiss")

Reading all list items

items = await bc.query_selector_all(conn, "ul.results li")
for node in items:
    text = await bc.get_text(conn, node)
    print(text)

Selecting a dropdown value

await bc.select_option(conn, "select#country", "US")

Keyboard shortcuts

# Ctrl+A then Delete
await bc.press_key(conn, "a", modifiers=2)   # Ctrl=2
await bc.press_key(conn, "Delete")

Capturing a single element screenshot

png = await bc.screenshot_element(conn, "#logo")
with open("logo.png", "wb") as f:
    f.write(png)

Running arbitrary JavaScript

count = await bc.evaluate(conn, "document.querySelectorAll('li').length")
print(f"Found {count} list items")

# Operate on a specific element
checked = await bc.evaluate_on_node(
    conn, "input[type='checkbox']",
    "function() { return this.checked; }"
)