fastcdp

Lightweight Chrome Debug Protocol (CDP) client for python

fastcdp provides an async Python client for the Chrome DevTools Protocol (CDP) over WebSocket. It auto-discovers Chrome’s debug port, loads the full protocol schema from bundled JSON files, and exposes every CDP domain as a Python attribute with auto-generated signatures and docstrings — e.g. await cdp.page.navigate(url=...).

It includes a Page class for tab-scoped operations, event subscription via cdp.on()/cdp.wait_event(), navigation helpers (goto, wait_for_selector, wait_for), screenshot capture, and accessibility tree access. A cdp_search utility lets you search CDP commands by name or description. For use inside safepyrun sandboxes, cdp_yolo() registers all CDP classes.

Installation

Install latest from pypi

$ pip install fastcdp

How to use

from fastcdp import *

Chrome 146+ has built-in remote debugging support. Navigate to chrome://inspect/#remote-debugging and enable “Allow remote debugging for this browser instance”:

image.png

Connect to Chrome (which will pop up a permissions window):

cdp = await CDP.connect()

Every CDP domain is available as an attribute with auto-generated signatures. You can search for commands with cdp_search:

cdp_search('screenshot')
"Emulation.setVisibleSize: Resizes the frame/viewport of the page. Note that this does not affect the frame's container\n(e.g. browser window). Can \nHeadlessExperimental.beginFrame: Sends a BeginFrame to the target and returns when the frame was completed. Optionally captures a\nscreenshot from the res\n  evt Overlay.screenshotRequested: Fired when user asks to capture screenshot of some area on the page.\nPage.captureScreenshot: Capture page screenshot."

List open pages and attach to one:

ps = await cdp.pages
pg = ps[0]
pg['title']
'l:SolveIT - scratch◀️chats'
tid = pg['targetId']
sid = await cdp.attach(tid)
await cdp.eval('document.title', sid)
'l:SolveIT - scratch◀️chats'

The Page class wraps a tab with its own session, so you don’t need to pass sid everywhere:

page = await cdp.new_page()
await page.goto('https://httpbin.org/forms/post')

You can wait_for any js expression to be truthy, and have it returned:

await page.wait_for('document.title')
'4. httpbin.org/forms/post'

Take a screenshot of the page:

img = await page.screenshot()

Clean up when done:

await page.close()
await cdp.close()

See CDP docs for full details.