Trio Chrome DevTools Protocol
Trio Chrome DevTools Protocol (Trio CDP) is a Python library that enables remote control of any web browser implementing the Chrome DevTools Protocol. It leverages Trio for asynchronous I/O and `python-chrome-devtools-protocol` for type wrappers. The library handles WebSocket negotiation and session management, allowing transparent multiplexing of commands, responses, and events over a single connection. The current version is 0.6.0, released in April 2020, with ongoing maintenance evident through recent GitHub activity.
Common errors
-
trio.TooSlowError: checkpoint timed out
cause This usually indicates that a long-running, CPU-bound synchronous operation is blocking the Trio event loop, preventing it from yielding control.fixIdentify and refactor synchronous blocking calls. If they are unavoidable, consider running them in a separate thread using `trio.to_thread.run_sync()` or moving them to a separate process. -
Error: Could not find DevToolsActivePort
cause The library failed to locate the file indicating the active DevTools port for a running Chrome instance. This often happens if Chrome is not running with remote debugging enabled or if the `--autoConnect` feature (if used via a wrapper) cannot find the debug port file.fixVerify that Chrome is running and launched with the `--remote-debugging-port=9222` (or your chosen port) flag. Also, ensure no firewall or sandbox restrictions are preventing access to the port or the temporary files Chrome creates for debugging. -
ProtocolError: <Domain.Method> timed out
-
The socket connection was closed unexpectedly
cause A network-level issue where the WebSocket connection to Chrome was dropped. This can be due to Chrome crashing, closing the tab/browser, an unstable network, or stricter sandbox/firewall settings.fixCheck if the Chrome instance is still running and the target tab is open. Ensure stable network connectivity. Review browser logs for crashes or relevant errors. If running in a containerized environment, ensure proper port forwarding and network access. Restarting Chrome with remote debugging might resolve transient issues. -
ProtocolError: Method '<Domain.Method>' not found
cause The command you are trying to execute is not supported by the connected browser's Chrome DevTools Protocol version, or the method name is misspelled.fixVerify that the browser version you are using is compatible with the `trio-chrome-devtools-protocol` and `python-chrome-devtools-protocol` versions you have installed. Consult the CDP documentation or `python-chrome-devtools-protocol` source to confirm method existence and spelling for your browser's protocol version.
Warnings
- breaking The Chrome DevTools Protocol itself is subject to frequent changes, especially the 'tip-of-tree' version. As `trio-chrome-devtools-protocol` relies on `python-chrome-devtools-protocol` (which generates its types from CDP), changes in the underlying protocol can lead to API mismatches or breakage if the library is not updated to match the browser's CDP version.
- gotcha Chrome/Chromium must be launched with the `--remote-debugging-port` flag (e.g., `--remote-debugging-port=9222`) for `trio-chrome-devtools-protocol` to connect. Without this, the browser will not expose the DevTools Protocol endpoint, leading to connection failures.
- gotcha To receive events (e.g., `page.LoadEventFired`, `network.RequestWillBeSent`), you must explicitly enable the corresponding CDP domain using methods like `session.page_enable()` or `session.network_enable()` before the event occurs. Events are not enabled by default.
- gotcha As `trio-chrome-devtools-protocol` is built on Trio, all asynchronous operations must be executed within a Trio event loop. Attempting to call `async` functions outside `trio.run()` or a `trio.lowlevel.checkpoint()` context will result in runtime errors.
Install
-
pip install trio-chrome-devtools-protocol
Imports
- open_cdp
from trio_cdp import open_cdp
- find_chrome_debugger_url
from trio_cdp import find_chrome_debugger_url
- page
from trio_cdp import page
- dom
from trio_cdp import dom
Quickstart
import trio
from trio_cdp import open_cdp, page, dom
async def main():
# Ensure Chrome is running with --remote-debugging-port=9222
cdp_url = 'http://localhost:9222'
target_url = 'https://www.example.com'
try:
async with open_cdp(cdp_url) as conn:
# Find the first available target (usually a browser tab).
# Note: target domain imports are typically implicitly available on 'conn.target'
targets = await conn.target.get_targets()
if not targets:
print('No targets found. Is Chrome running and a page open?')
return
target_id = targets[0].id
# Create a new session with the chosen target.
async with conn.open_session(target_id) as session:
# Enable page-level events to wait for navigation completion.
async with session.page_enable():
async with session.wait_for(page.LoadEventFired):
await session.execute(page.navigate(target_url))
print(f"Navigated to: {target_url}")
# Extract the page title.
root_node = await session.execute(dom.get_document())
title_node_id = await session.execute(dom.query_selector(root_node.node_id, 'title'))
if title_node_id:
html = await session.execute(dom.get_outer_html(title_node_id))
print(f"Page Title HTML: {html}")
else:
print("Could not find title element.")
except Exception as e:
print(f"An error occurred: {e}")
print("Make sure Chrome is running with '--remote-debugging-port=9222'.")
if __name__ == '__main__':
trio.run(main)