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 five 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.
  • async with CDP.testing(headless=True) as cdp: owns a disposable Chrome for Testing and temporary profile. Install it once with fastcdp-setup --install stable; the context closes the browser and removes the profile when finished. It leaves your installed Chrome and CDP Chrome setup untouched.

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.15

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.15
File Size Uploaded
fastcdp-0.0.15.tar.gz 293.2 kB Details

Built distribution (wheel)

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

Total release size: 587.7 kB

Release files / fastcdp-0.0.15.tar.gz

Download URL fastcdp-0.0.15.tar.gz
Size 293.2 kB
Tags Source
SHA-256 checksum
How to use checksums
8c7433a1d2110c3c4dcd2de59e1cf66edafbb2d545ea9eb20c677c011b40191f
BLAKE2b-256 checksum
How to use checksums
f443af03ec9e16fd1fa11ab491736e25d9272501e5048ed179e496933ad40fb6
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.15-py3-none-any.whl

Download URL fastcdp-0.0.15-py3-none-any.whl
Size 294.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
98702413fd97f90e1321ece7bd3e857b868795a9ce2593eaca33083fac0561b3
BLAKE2b-256 checksum
How to use checksums
6c7f7048743a5fa7611865bc096b251378d82183328cb60c76523d73d3151e79
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.15 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