Skip to main content

fastcdp

fastcdp is an async Python client for the Chrome DevTools Protocol (CDP) over WebSocket. Use it to automate your everyday Chrome browser or a separate Chrome instance. It can launch Chrome or connect to a running browser.

Every CDP domain is available as a Python attribute, such as await cdp.page.navigate(url=...). fastcdp loads the full protocol schema from bundled JSON files to generate signatures and docstrings. It discovers Chrome’s debug port automatically.

The Page class provides tab-scoped operations for navigation, content waits, screenshots, and accessibility tree access. The examples below use it to inspect and fill a form.

Installation

Install latest from pypi

$ pip install fastcdp

How to use

from fastcdp import *

Choose one of four connection methods. Read doc(fastcdp.skill) for browser-selection and ownership guidance, then the chosen method’s full docs:

  • cdp = await CDP.launch() starts or reuses Chrome with a separate automation profile. The default profile persists between runs.
  • cdp = await CDP.connect() attaches to an everyday Chrome with remote debugging enabled and the user’s approval.
  • cdp = await CDP.remote() attaches to a dedicated debug browser. fastcdp-setup creates a launcher for this configuration.
  • cdp = await ExtCDP.listen() waits for the fastcdp-chrome extension in the requested browser.

This walkthrough uses connect:

In Chrome 146 or later, open chrome://inspect/#remote-debugging and enable “Allow remote debugging for this browser instance”:

image.png

The CDP class

Connect to Chrome and approve its permission prompt:

cdp = await CDP.connect()

Use cdp.on() to subscribe to events or cdp.wait_event() to wait for an event. To find commands by name or description, use 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']
'8. Database Transactions — PlanetScale'
tid = pg['targetId']
sid = await cdp.attach(tid)
await cdp.eval('document.title', sid)
'8. Database Transactions — PlanetScale'

Page holds a tab’s session. Its helpers bind sid. Read doc(page) to discover those helpers and protocol domains, then doc(page.goto) or doc(page.DOM.focus) for a selected operation. Connection-wide operations such as creating tabs remain on page.cdp:

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

Choose how goto waits for navigation:

  • By default, it waits for the document’s load event.
  • wait='idle' also waits for initial network activity to settle.
  • wait=None skips the navigation wait. Use a subsequent content wait to check application-specific readiness.

wait_for_selector waits for an element. wait_for waits for a JavaScript expression to become truthy and returns its value:

await page.wait_for('document.title')
'6. 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.

Page.new and filling forms

Call Page.new() without arguments to create a CDP object and attach it to a new page:

page = await Page.new()
await page.goto('https://httpbingo.org/forms/post')

Use ax_tree to find elements through the accessibility tree. Pass frame_id= to read a child frame directly:

root = await page.ax_tree()
print(str(root)[:300])
- **RootWebArea** "6. httpbin.org/forms/post" `focusable=True` `focused=True` `url=https://httpbin.org/forms/post` [#2]
  - **LabelText** "" [#24]
    - **StaticText** "Customer name: " [#64]
      - **InlineTextBox** "Customer name: "
    - **textbox** "Customer name: " `focusable=True` `editable=p

Use find and find_id to locate elements in the tree:

nmid = root.find_id('textbox', 'Customer name')
nmid
4

page.attrs reads an element’s HTML attributes by node id or CSS selector. For example, await page.attrs(nmid) and await page.attrs('[name=custname]') each return a dictionary.

await page.sel_attrs('input', 'name', 'type') returns one dictionary per matching element. Missing requested attributes have the value None. Omit the attribute names to read all attributes.

Interact with elements using CDP methods or these shortcuts:

await page.fill_text(nmid, 'Jeremy Howard')
await page.click(root.find_id('radio', 'Large'))
await page.js_node_run('this.value = "18:30"', root.find_id('InputTime', 'delivery time'))
{'type': 'undefined'}

Choose the input method according to the interaction you need:

  • click moves the real mouse before pressing and releasing.
  • tap sends a trusted Chrome tap gesture without moving the mouse. Use it when mouse movement is unreliable or hover is undesirable.
  • dom_click calls the element’s JavaScript activation. It does not produce trusted input.

click_and_wait clicks and waits for a top-frame navigation. For another activation method, use expect_navigation around that operation. For in-place UI updates, activate the element normally and wait for the resulting content.

await page.click_and_wait(root.find_id('button', 'Submit order'))

When using page.New(), close() also shuts down the CDP websocket.

await page.close()

For an LLM using fastcdp through safepyrun, such as in Solveit, register all CDP classes with:

cdp_yolo()

Then open a controlled page for it:

page = await Page.new()

Then use a prompt such as:

Try using python to go to <url> using the existing page, fill it out, read it to check it’s filled correctly, then submit it, and see what you get back. Don’t use find_id - you can get all the ids at once with ax_tree (don’t truncate the result of it). Don’t add extra waits etc - fastcdp handles it automatically. IDs can change so be sure to use the ax_tree IDs you read.

Release files for fastcdp 0.0.14

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastcdp 0.0.14
File Size Uploaded
fastcdp-0.0.14.tar.gz 290.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fastcdp 0.0.14
File Interpreter ABI Platform
fastcdp-0.0.14-py3-none-any.whl Python 3 none any Details

Total release size: 582.4 kB

Release files / fastcdp-0.0.14.tar.gz

Download URL fastcdp-0.0.14.tar.gz
Size 290.5 kB
Tags Source
SHA-256 checksum
How to use checksums
020b89d24ce8cd55fe204e9092b1e71173c801f48982b238b48304ea5d91dc48
BLAKE2b-256 checksum
How to use checksums
298ad53a6bffc341c6273616242bb947ec0a63b560cb20bc446200e1434434ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release files / fastcdp-0.0.14-py3-none-any.whl

Download URL fastcdp-0.0.14-py3-none-any.whl
Size 291.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d907dd2067ccbbc9c855aa22a7d2d8ecdb3f0dc2981cfb88e505cdfa0eb0a67f
BLAKE2b-256 checksum
How to use checksums
bff6b67428c5d1faf263544f0f3a5eee7831ca15898e6f569c6498f4eef9dfb0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release history Release notifications | RSS feed

0.0.17

2 release files

This release

0.0.14 This release

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page