Metadata-Version: 2.4
Name: pycdp-automation
Version: 0.1.0
Summary: Async Chromium automation over a browser-level CDP WebSocket
Author: thuctran63
License-Expression: MIT
Project-URL: Homepage, https://github.com/thuctran63/pycdp-automation
Project-URL: Repository, https://github.com/thuctran63/pycdp-automation
Project-URL: Issues, https://github.com/thuctran63/pycdp-automation/issues
Keywords: automation,cdp,chrome-devtools-protocol,chromium,websocket
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: websockets>=12
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: ruff>=0.12; extra == "dev"
Requires-Dist: twine>=6; extra == "dev"
Requires-Dist: pyright>=1.1.400; extra == "dev"
Dynamic: license-file

# CDP Automation

[![PyPI](https://img.shields.io/pypi/v/pycdp-automation.svg)](https://pypi.org/project/pycdp-automation/)
[![Python](https://img.shields.io/pypi/pyversions/pycdp-automation.svg)](https://pypi.org/project/pycdp-automation/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

A small Python 3.11+ library for asynchronous Chromium automation over a direct Chrome DevTools Protocol WebSocket.

> This library connects to an already-running Chromium browser via its browser-level Chrome DevTools Protocol WebSocket endpoint. It does not launch or manage Chromium.

It does not use Playwright, Selenium, Puppeteer, Node.js, subprocesses, or a per-command connection.

## Architecture

`Browser` owns one persistent `CDPConnection`. The connection has one receive coroutine, multiplexes concurrent requests by ID, dispatches events, and routes target-scoped traffic to `CDPSession`. `Page` and `Element` expose the high-level API and never access the WebSocket directly.

```text
Profile Manager -- ws_url --> Browser --> CDPConnection --> persistent WebSocket
                                  |             |
                                Page <-- CDPSession
                                  |
                               Element
```

The Profile Manager integration boundary is only the URL:

```python
ws_url = await profile_manager.open(profile)
browser = await Browser.connect(ws_url)
```

Neither component imports the other.

## Installation

```text
pip install pycdp-automation
```

The distribution name is `pycdp-automation`; the import package is `cdp_automation`. Runtime dependency: `websockets`. For local development, use `pip install -e ".[dev]"`.

## Usage

```python
from cdp_automation import Browser

browser = await Browser.connect(ws_url)
try:
    page = await browser.get_active_page()
    await page.goto("https://example.com")
    await page.fill("#username", "hello")
    await page.type("#password", "123456", delay=50)
    await page.keyboard.press("Control+A")
    await page.click("#login")
    print(await page.text_content(".profile-name"))
finally:
    await browser.disconnect()
```

Context-manager form (because `connect` is async, await its result):

```python
async with await Browser.connect(ws_url) as browser:
    page = await browser.get_active_page()
    await page.goto("https://example.com")
```

## Public API

- `Browser`: `connect`, `disconnect`, `pages`, `get_active_page`, `new_page`, `close_page`, `refresh_targets`, and cookie methods.
- `Page`: navigation, evaluation, CSS queries, mouse/keyboard devices, fill/type/press, hover/focus, checkbox and select controls, file upload, dialog and function waits, text/state access, screenshot, and events.
- `Element`: click, hover, focus/blur, scrolling/bounding box, fill/type/press, checkbox/select/upload actions, value/state/text/attribute access, and explicit disposal.
- `Keyboard`: key down/up, chords such as `Control+A`, Unicode text insertion, modifiers, navigation keys, and function keys.
- `Mouse`: move, down/up, click/double-click, right/middle click, and wheel scrolling.
- `Dialog`: inspect alert/confirm/prompt dialogs and accept or dismiss them.
- Errors: `CDPError`, `CDPConnectionError`, `CDPTimeoutError`, `TargetClosedError`, `ElementNotFoundError`, and `NavigationError`.

Public timeout values use milliseconds. Defaults are 10 seconds for general operations and 30 seconds for navigation. Override them with `page.set_default_timeout(...)` and `page.set_default_navigation_timeout(...)`.

Commands on multiple pages can be run with `asyncio.gather`; responses need not arrive in send order. Every `Browser` has independent connection state.

## Logging and protocol safety

The library uses standard `logging`. Normal debug logs contain command names and lifecycle data, not values such as form input or JavaScript expressions. `debug_protocol=True` enables additional protocol metadata but still does not log message payloads.

Only `ws://` and `wss://` endpoints are accepted. A browser restart permanently invalidates the instance; obtain a new URL from the Profile Manager and create a new `Browser`. There is intentionally no silent reconnect.

## Tests

Unit tests use an in-memory fake WebSocket and cover response routing, out-of-order responses, protocol errors, timeout, disconnect, event dispatch, and session routing. The integration test runs only when `CDP_WS_URL` is set.

## Known limitations

CSS selectors currently address the main document only. The library does not yet provide iframe or shadow-DOM abstractions, network request/response models, downloads, interception, tracing, video, process launch, proxy/fingerprint configuration, or auto-reconnect. Navigation is serialized per page and correlated through main-frame lifecycle events and loader IDs. `fill` uses native value setters plus `input`/`change` events, while `type` uses CDP text insertion. File paths for upload must be accessible to the Chromium host. Stale remote handles raise `StaleElementError`.

## Phase 2 ideas

- Frame-aware execution contexts and selectors
- Shadow DOM traversal
- Full-page screenshots and viewport control
- Event-based URL waits and richer lifecycle tracking
- Network controls, downloads, and optional request interception
