Overview
Python Chrome DevTools Protocol (shortened to PyCDP) is a library that provides Python wrappers for the types, commands, and events specified in the Chrome DevTools Protocol.
The Chrome DevTools Protocol provides for remote control of a web browser by sending JSON messages over a WebSocket. That JSON format is described by a machine-readable specification. This specification is used to automatically generate the classes and methods found in this library.
You could write a CDP client by connecting a WebSocket and then sending JSON objects, but this would be tedious and error-prone: the Python interpreter would not catch any typos in your JSON objects, and you wouldn’t get autocomplete for any parts of the JSON data structure. By providing a set of native Python wrappers, this project makes it easier and faster to write CDP client code.
Two usage modes are available:
Sans-I/O mode (original): The core library provides type wrappers without performing any I/O. This maximises flexibility and allows integration with any async framework such as trio-chrome-devtools-protocol.
I/O mode: The
cdp.connectionmodule handles the WebSocket lifecycle, JSON-RPC message framing, and command multiplexing. Thecdp.browser_controlmodule layers a high-level automation API on top of this, providing Playwright-style helpers for navigation, element interaction, screenshots, and more. See Browser Control for details.
This package provides Chrome DevTools Protocol r678025. Download a compatible Chrome package:
Install from PyPI (requires Python ≥3.8):
$ pip install chrome-devtools-protocol # Sans-I/O only
$ pip install chrome-devtools-protocol[io] # With WebSocket / browser-control support
Quick example (Sans-I/O mode):
from cdp import page
frame_id = page.FrameId('my id')
assert repr(frame_id) == "FrameId('my id')"
Quick example (browser control):
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:
await conn.execute(page.enable())
await bc.navigate(conn, "https://example.com")
await bc.wait_for_load(conn)
print(await bc.get_text(conn, "h1"))
asyncio.run(main())