A Python Package for the Google Chrome Dev Protocol
pychrome is a Python package designed for interacting with Google Chrome via the Chrome DevTools Protocol. It enables automation and inspection of web pages, allowing users to control browser behavior, capture network traffic, manipulate the DOM, and more. The current version is 0.2.4, with development actively maintained on GitHub.
Common errors
-
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionRefusedError(111, 'Connection refused'))cause The Chrome browser is not running with the remote debugging port enabled, or `pychrome` is trying to connect to the wrong IP address or port.fixEnsure Chrome is running with `--remote-debugging-port=9222` (or your chosen port). Verify the `url` parameter in `pychrome.Browser(url='http://127.0.0.1:9222')` matches. Check firewall settings or if another process is using the port. -
websocket._exceptions.WebSocketBadStatusException: Handshake status 400 Bad Request
cause This often indicates an incompatibility between the `pychrome` client and the Chrome DevTools Protocol version, or an issue with the Chrome instance itself, potentially due to a recent browser update.fixUpdate `pychrome` to the latest version (`pip install -U pychrome`). If the issue persists, try using an older, stable version of the Chrome browser that is known to be compatible with your `pychrome` version. Check GitHub issues for `pychrome` for specific reports related to your Chrome version. -
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
cause This error typically occurs when `pychrome` receives an unexpected, non-JSON response from the Chrome DevTools endpoint, often indicating a problem with the connection or the Chrome browser's debugging interface. This has been reported with specific Chrome versions.fixVerify that Chrome is properly started with the `--remote-debugging-port` flag and that no other application is interfering with the port. Restart Chrome. If the problem persists, this might be a browser version incompatibility; refer to `pychrome`'s GitHub issues for guidance or try a different Chrome version.
Warnings
- breaking Breaking changes in Chrome browser versions can unexpectedly affect `pychrome`'s functionality, especially regarding the DevTools Protocol. Specific issues have been reported with changes to tab management and WebSocket connections after Chrome updates.
- gotcha The Chrome browser must be launched with the remote debugging port enabled (e.g., `--remote-debugging-port=9222`) for `pychrome` to connect. Forgetting this flag or using an incorrect port will lead to connection failures.
- gotcha Issues might arise when closing tabs or managing multiple tabs, sometimes leading to exceptions or zombie processes if not handled gracefully.
Install
-
pip install -U pychrome
Imports
- Browser
from pychrome import Browser
import pychrome browser = pychrome.Browser()
- Tab
import pychrome browser = pychrome.Browser() tab = browser.new_tab()
Quickstart
import pychrome
import os
import subprocess
import time
# --- Step 1: Ensure Chrome is running with remote debugging enabled ---
# This command typically opens Chrome (or a headless instance) on port 9222.
# Adjust the path to your Chrome executable if needed.
# For headless mode: 'google-chrome --headless --disable-gpu --remote-debugging-port=9222'
# Check if Chrome is already running on the debug port
try:
# Attempt to connect to check if a browser is already listening
_ = pychrome.Browser(url="http://127.0.0.1:9222").list_tab()
print("Chrome with remote debugging already running.")
except Exception:
print("Starting Chrome with remote debugging...")
# Example for Linux/macOS. Adjust for Windows (e.g., 'start chrome.exe ...')
# Using os.environ.get for robustness in different environments
chrome_cmd = os.environ.get('CHROME_EXECUTABLE', 'google-chrome')
try:
# Start Chrome in headless mode for automation
subprocess.Popen([chrome_cmd, '--headless', '--disable-gpu', '--remote-debugging-port=9222'],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
time.sleep(2) # Give Chrome a moment to start up
except FileNotFoundError:
print(f"Error: Chrome executable '{chrome_cmd}' not found. Please set CHROME_EXECUTABLE environment variable or ensure Chrome is in your PATH.")
exit(1)
# --- Step 2: Connect to Chrome and perform actions ---
browser = pychrome.Browser(url="http://127.0.0.1:9222")
# List existing tabs or create a new one
tabs = browser.list_tab()
if not tabs:
tab = browser.new_tab()
else:
# Use the first available tab, or iterate to find a specific one
tab = tabs[0]
def request_will_be_sent(**kwargs):
"""Callback function to print URLs of outgoing requests"""
url = kwargs.get('request', {}).get('url')
if url:
print(f" Loading: {url}")
try:
print(f"Interacting with tab: {tab.id}")
tab.start()
tab.Network.enable()
tab.Network.requestWillBeSent = request_will_be_sent # Register callback
print("Navigating to example.com...")
tab.Page.navigate(url="https://www.example.com", _timeout=5)
tab.wait(5) # Wait for page to load events for 5 seconds
# Execute some JavaScript on the page
result = tab.Runtime.evaluate(expression="document.title")
print(f"Page title: {result['result']['value']}")
finally:
# Clean up: stop the tab and close it
if tab:
tab.stop()
browser.close_tab(tab.id)
print(f"Closed tab: {tab.id}")
# In a real application, you might also want to close the browser process
# if it was started by your script, but care is needed not to close
# a user's active browser session.