Skip to main content

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.

Documentation

Full documentation is auto-generated and published at: https://sohaib17.github.io/pypecdp/

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}")

Customization via Inheritance

pypecdp is designed to be easily extended through OOP inheritance:

from pypecdp import Browser, Tab, Elem

class MyElem(Elem):
    async def click_and_wait(self, timeout=10.0):
        """Click and wait for page load."""
        tab = await self.click()
        if tab:
            await tab.wait_for_event(cdp.page.LoadEventFired, timeout=timeout)
        return tab

class MyTab(Tab):
    elem_class = MyElem  # Use custom Elem class
    
    async def search(self, query):
        """Custom search method."""
        search_box = await self.wait_for_elem("#search")
        await search_box.type(query)

class MyBrowser(Browser):
    tab_class = MyTab  # Use custom Tab class

# Use your custom classes
browser = await MyBrowser.start()
tab = await browser.navigate("https://example.com")
# tab is now MyTab instance, elements are MyElem instances

See example/customize_pypecdp.py for working example.

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

pypecdp-0.6.2.tar.gz (298.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pypecdp-0.6.2-py3-none-any.whl (309.9 kB view details)

Uploaded Python 3

File details

Details for the file pypecdp-0.6.2.tar.gz.

File metadata

  • Download URL: pypecdp-0.6.2.tar.gz
  • Upload date:
  • Size: 298.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pypecdp-0.6.2.tar.gz
Algorithm Hash digest
SHA256 88d7a01f0800ed6c61672028841d55d4444cb841b8e35265073fff4d3a37ffa4
MD5 33e0275060e592171e40f51c840f4a46
BLAKE2b-256 91e3d6e661a8140ba1295fe8332bb1e58d0bc0f9c5b7a3988916e145d600fd97

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypecdp-0.6.2.tar.gz:

Publisher: publish-to-pypi.yml on sohaib17/pypecdp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypecdp-0.6.2-py3-none-any.whl.

File metadata

  • Download URL: pypecdp-0.6.2-py3-none-any.whl
  • Upload date:
  • Size: 309.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pypecdp-0.6.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d79f67cfff7d5343c3ba790e46ecaf3845ce3f9f52fcef6e7fced2775684d692
MD5 5b7d590eeb0b7bcfdd5e07b6bfde0b88
BLAKE2b-256 618093ec5e5d3b0c07085663faa6f37f4a49297ef049da21d7add581a51c5c7c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypecdp-0.6.2-py3-none-any.whl:

Publisher: publish-to-pypi.yml on sohaib17/pypecdp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page