Async Chrome DevTools Protocol over POSIX pipes.
Project description
pypecdp
Fully async Chrome DevTools Protocol over POSIX pipes with a high-level Browser/Tab/Elem API for Python 3.12+ on Linux.
Chrome automation using --remote-debugging-pipe (no websockets, no ports, just pipes) with bundled CDP protocol classes.
Inspired by playwright-python, python-cdp and nodriver.
Features
- Fully Async: Built from ground up with asyncio for concurrent operations
- Fast: Direct pipe communication via file descriptors - no websockets, no network overhead
- Minimal dependencies: Only one dependency (
deprecated) - lightweight and easy to install - Secure: Browser only communicates over local pipes, no open ports accessible to other processes
- No zombies: No risk of orphaned Chrome processes if code crashes - automatic lifecycle management
- Linux focused: Leverages POSIX pipes and process management
Install
pip install pypecdp
Install Chromium if needed:
# Ubuntu/Debian
sudo apt-get install chromium-browser
# Fedora
sudo dnf install chromium
# Arch
sudo pacman -S chromium
Quick Start
import asyncio
from pypecdp import Browser
async def main():
# Launch browser
browser = await Browser.start(
chrome_path="chromium",
headless=True
)
# Navigate to a URL (creates/reuses a tab)
tab = await browser.navigate("https://example.com")
# Select and interact with elements
h1 = await tab.wait_for_elem("h1")
if h1:
text = await h1.text()
print(f"Page heading: {text}")
# Evaluate JavaScript
result = await tab.eval("document.title")
print(f"Title: {result.value}")
# Close browser
await browser.close()
asyncio.run(main())
Usage Guide
Browser Management
from pypecdp import Browser, Config
# Simple start
browser = await Browser.start(chrome_path="chromium", headless=True)
# Advanced configuration
config = Config(
chrome_path="/usr/bin/google-chrome",
user_data_dir="/tmp/chrome-profile",
clean_data_dir=False, # Preserve existing profile data
headless=True,
extra_args=["--no-sandbox", "--disable-gpu"],
env={"LANG": "en_US.UTF-8"}
)
browser = await Browser.start(config=config)
# Close browser
await browser.close()
Note: By default, clean_data_dir=True which removes any existing user data directory before starting. Set it to False to preserve cookies, cache, and other browser state between runs.
Element Interactions
# Finding and clicking elements
button = await tab.wait_for_elem("button.submit")
if button:
await button.click()
# Clicking elements that cause navigation
link = await tab.wait_for_elem('a[href="/next-page"]')
if link:
# click() returns the top-level Tab after navigation
current_tab = await link.click()
if current_tab:
# Wait for the new page to load
await current_tab.wait_for_event(cdp.page.LoadEventFired, timeout=10.0)
print(f"Navigated to: {current_tab.url}")
Event Handlers
from pypecdp import cdp
# Tab-level events (requires domain enable!)
await tab.send(cdp.runtime.enable()) # Required for runtime events!
async def on_console(event):
print(f"Console {event.type_}: {event.args}")
tab.on(cdp.runtime.ConsoleAPICalled, on_console)
# Browser-level events
async def on_target_created(event):
info = event.target_info
print(f"Target created: {info.type_} - {info.url}")
browser.on(cdp.target.TargetCreated, on_target_created)
Logging
pypecdp uses Python's standard logging module. Configure via environment variables:
# Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
export PYPECDP_LOGLEVEL=DEBUG
# Set custom logger name
export PYPECDP_LOGGER=myapp.browser
Or configure the logger directly in Python:
from pypecdp import logger
import logging
# Set log level
logger.setLevel(logging.DEBUG)
# Add custom handler
handler = logging.FileHandler("pypecdp.log")
logger.addHandler(handler)
Error Handling
try:
browser = await Browser.start()
tab = await browser.navigate("https://example.com")
# Your automation code
elem = await tab.wait_for_elem("button")
if elem:
await elem.click()
result = await tab.eval("document.title")
except ReferenceError as e:
# Element's tab is no longer available (closed/detached)
print(f"Target Error: {e}")
except RuntimeError as e:
# CDP protocol errors
print(f"CDP Error: {e}")
except ConnectionError as e:
# Connection lost
print(f"Connection Error: {e}")
except Exception as e:
# Other errors
print(f"Error: {e}")
finally:
# Always cleanup
await browser.close()
Requirements
- Python 3.12+
- Linux (uses POSIX pipes and
preexec_fn) - Chromium or Google Chrome
Links
License
MIT License - See LICENSE file for details.
Contributing
Contributions welcome! This project aims to provide a clean, type-safe interface to Chrome automation on Linux.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pypecdp-0.5.0.tar.gz.
File metadata
- Download URL: pypecdp-0.5.0.tar.gz
- Upload date:
- Size: 280.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f9ebf9e094c7a876456de4c77ed309737caeae84fe4f5f485a0959dfb09039c0
|
|
| MD5 |
d6fc82197d8b31b25a4ce5c64b24f03d
|
|
| BLAKE2b-256 |
4dacab492d3c658e835d7577bb4252b8aed4705f95fa3e333d76f2d86c974fe0
|
Provenance
The following attestation bundles were made for pypecdp-0.5.0.tar.gz:
Publisher:
publish-to-pypi.yml on sohaib17/pypecdp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pypecdp-0.5.0.tar.gz -
Subject digest:
f9ebf9e094c7a876456de4c77ed309737caeae84fe4f5f485a0959dfb09039c0 - Sigstore transparency entry: 832850261
- Sigstore integration time:
-
Permalink:
sohaib17/pypecdp@837fe1a7597bdbaf48d54f91e3c62327798719f7 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/sohaib17
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@837fe1a7597bdbaf48d54f91e3c62327798719f7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pypecdp-0.5.0-py3-none-any.whl.
File metadata
- Download URL: pypecdp-0.5.0-py3-none-any.whl
- Upload date:
- Size: 297.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6242217beb5e41246a26f6090f9171759db7e5590d07e026d52414ef7fea7844
|
|
| MD5 |
e0d6d6bbb0f4ea7a2883d67445d6ff56
|
|
| BLAKE2b-256 |
79c781ea68bea5e8b2524392f7cfa590266c0fcd4b145eb7f5e87471947ddc77
|
Provenance
The following attestation bundles were made for pypecdp-0.5.0-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on sohaib17/pypecdp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pypecdp-0.5.0-py3-none-any.whl -
Subject digest:
6242217beb5e41246a26f6090f9171759db7e5590d07e026d52414ef7fea7844 - Sigstore transparency entry: 832850262
- Sigstore integration time:
-
Permalink:
sohaib17/pypecdp@837fe1a7597bdbaf48d54f91e3c62327798719f7 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/sohaib17
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@837fe1a7597bdbaf48d54f91e3c62327798719f7 -
Trigger Event:
release
-
Statement type: