Metadata-Version: 2.4
Name: playwright-cdp-probe
Version: 0.2.4
Summary: Playwright bot-detection probe — score CDP for webdriver and headless leaks. CLI: cdp-probe.
Project-URL: Homepage, https://pypi.org/project/playwright-cdp-probe/
Project-URL: Documentation, https://pypi.org/project/playwright-cdp-probe/
Project-URL: Repository, https://github.com/playwright-cdp-probe/playwright-cdp-probe
Project-URL: Issues, https://github.com/playwright-cdp-probe/playwright-cdp-probe/issues
Project-URL: Changelog, https://github.com/playwright-cdp-probe/playwright-cdp-probe/blob/main/CHANGELOG.md
Author: playwright-cdp-probe contributors
License-Expression: MIT
License-File: LICENSE
Keywords: anti-bot-testing,automation-exposure,bot-detection,bot-score,cdp-probe,exposure-score,headless-fingerprint,navigator-webdriver,puppeteer-audit,selenium-audit,stealth-audit,webdriver-leak
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: click>=8.1
Requires-Dist: playwright>=1.40
Provides-Extra: dev
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest-httpx>=0.34; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Provides-Extra: mlx
Requires-Dist: httpx>=0.27; extra == 'mlx'
Description-Content-Type: text/markdown

# playwright-cdp-probe

**Playwright bot-detection probe** — score CDP sessions for webdriver, headless Chrome, and WebGL exposure.

[![PyPI version](https://img.shields.io/pypi/v/playwright-cdp-probe.svg)](https://pypi.org/project/playwright-cdp-probe/)
[![Python versions](https://img.shields.io/pypi/pyversions/playwright-cdp-probe.svg)](https://pypi.org/project/playwright-cdp-probe/)
[![License: MIT](https://img.shields.io/pypi/l/playwright-cdp-probe.svg)](https://pypi.org/project/playwright-cdp-probe/)

```bash
pip install playwright-cdp-probe
cdp-probe check-local
```

CLI: **`cdp-probe`** · Python **3.10+** · optional **`[mlx]`** for Launcher helpers


> **Coupon hub:** Verified MLX deals (`SAAS50` browser / `MIN50` cloud phone) — [Multilogin promo codes](https://anti-detect.github.io/). Core CLI works without a vendor account. [Affiliate disclosure](docs/AFFILIATE.md).

Audit Playwright and CDP browser sessions for **automation exposure signals** — `navigator.webdriver`, `chrome.runtime`, plugin counts, permissions API, headless UA hints, and window/WebGL fingerprints.

Returns a **0–100 exposure score** (higher = more detectable automation artifacts). Use in CI, before production deploys, or to compare vanilla Chromium vs isolated antidetect profiles.

## Problem

Bot-detection stacks probe dozens of browser signals beyond IP and cookies. Before shipping automation to production, teams need a quick way to answer:

- Does this browser context leak `navigator.webdriver`?
- Are headless or SwiftShader fingerprints visible?
- How does a CDP-attached session compare to a local Playwright launch?

`cdp-probe` launches Playwright (or connects over CDP), collects signals in-page, and scores automation exposure with a reproducible report.

## Install

```bash
pip install playwright-cdp-probe
playwright install chromium   # first-time browser binaries
```

Optional Multilogin X launcher integration (compare isolated profile scores — not required for core probe):

```bash
pip install playwright-cdp-probe[mlx]
```

Development:

```bash
pip install playwright-cdp-probe[dev]
```

## Quick start

```bash
# Baseline: how detectable is default Playwright Chromium?
cdp-probe check-local --browser chromium

# Probe a live page (login gates, dashboards, SaaS apps)
cdp-probe run --url https://example.com

# Site-class presets (weighted for common gate pages — see presets/)
cdp-probe run --preset cloudflare --url https://example.com
cdp-probe run --preset stripe-dashboard --url https://dashboard.stripe.com
cdp-probe run --preset social-login --url https://example.com/login

# CI / GitHub Actions annotations
cdp-probe run --url https://example.com --format github-actions

# Re-print the last report
cdp-probe report --format table
cdp-probe report --format json
```

```python
from playwright_cdp_probe import ProbeRunner
from playwright_cdp_probe.probe import ProbeOptions

report = ProbeRunner(ProbeOptions(url="https://example.com")).run()
print(report.exposure.score, report.exposure.grade)
for finding in report.exposure.findings:
    print(finding.signal, finding.detail)
```

## CLI

| Command | Description |
|---------|-------------|
| `cdp-probe run --url URL` | Launch browser, navigate, score exposure |
| `cdp-probe run --preset NAME --url URL` | Score with site-class weights (`presets/`) |
| `cdp-probe check-local --browser chromium\|firefox` | Probe `about:blank` locally |
| `cdp-probe report --format json\|table\|github-actions` | Format last saved report |
| `cdp-probe mlx --profile-id UUID` | MLX Launcher → CDP probe → stop (`[mlx]` extra) |
| `cdp-probe --show-deal` | Print partner coupon info (opt-in only) |

### Exit codes

| Code | Meaning |
|------|---------|
| `0` | **pass** — exposure score ≤ 30 |
| `1` | **warn** — exposure score 31–60 |
| `2` | **fail** — exposure score > 60 |
| `3` | Runtime / validation error |

Signal weights and bands: [docs/SCORING.md](docs/SCORING.md).

### Presets

| Preset | Best for | Signals emphasized |
|--------|----------|-------------------|
| `cloudflare` | Turnstile / JS challenge pages | `HeadlessChrome` UA, `webdriver`, SwiftShader WebGL |
| `stripe-dashboard` | Payment / SaaS dashboards | Thin plugins, missing `chrome.runtime` |
| `social-login` | OAuth popups | `webdriver`, headless window dimensions |

Reports save to `~/.cache/cdp-probe/last-report.json` (override with `--output`).

## When exposure scores stay high

Vanilla Playwright Chromium often lands in the **warn** or **fail** band — that is expected, not a misconfiguration.

| Step | Action |
|------|--------|
| 1 | Read findings in `cdp-probe report --format table` — which signals fired? |
| 2 | Lint static fingerprint config with [fingerprint-coherence](https://pypi.org/project/fingerprint-coherence/) (`fp-coherence audit`) |
| 3 | Re-probe over **remote CDP** or an antidetect Launcher port instead of `launch()` |
| 4 | Compare scores: `check-local` vs profile-attached session — quantify the delta |
| 5 | Validate proxy + cookies: [proxy-lane-checker](https://pypi.org/project/proxy-lane-checker/) → [cookie-jar-bridge](https://pypi.org/project/cookie-jar-bridge/) |

**Full fleet QA pipeline:**

```bash
proxy-lane check proxies.txt -o lanes.json
fp-coherence audit profile.yaml --strict
cdp-connect mlx-start --profile-id UUID --print-cdp-url   # peer: cdp-connect-kit
cdp-probe run --cdp-endpoint "$CDP_URL" --url https://example.com --format github-actions
cookie-bridge validate session-cookies.txt --strict
```

**Coupon hub:** [Multilogin promo codes](https://anti-detect.github.io/) — guides for `SAAS50` / `MIN50`, pricing comparisons, and workflow playbooks.

Isolated antidetect browsers provision OS, screen, WebGL, and storage at the **profile** level — often a better fix than patching individual JS APIs. If you evaluate Multilogin X for production profile pools, see [Production](#production) (affiliate disclosure applies; core probe needs no vendor account).

## API

| Symbol | Description |
|--------|-------------|
| `ProbeRunner` | Launch Playwright or `connect_over_cdp`, collect signals |
| `ProbeOptions` | `url`, `browser`, `headless`, `cdp_endpoint` |
| `compute_exposure_score(signals)` | Score 0–100 with weighted findings |
| `ProbeReport` | Signals + exposure + timestamp |
| `format_report(report, "json"\|"table")` | CLI-compatible formatting |

### Signals collected

- `navigator.webdriver`
- `window.chrome.runtime` (Chromium)
- `navigator.plugins` / `mimeTypes` counts
- `navigator.permissions` API presence
- `Notification.permission`
- HeadlessChrome user-agent hint
- Window outer/inner dimension mismatch
- WebGL vendor/renderer (SwiftShader detection)

## Limitations

- **Not a bypass tool** — measures exposure; does not patch, spoof, or hide fingerprints.
- **Vanilla Chrome/Playwright leaks at scale** — default launches routinely expose `webdriver` and headless WebGL. High scores are normal.
- **Page-level only** — TLS/JA3, IP reputation, behavioral biometrics, and server-side ML are out of scope.
- **Single-page snapshot** — one navigation moment, not long-session drift.
- **Firefox signal set differs** — `chrome.runtime` checks apply to Chromium only.
- **MLX requires desktop agent** — `mlx` needs Multilogin running locally. See [docs/MLX_INTEGRATION.md](docs/MLX_INTEGRATION.md).

## Production

For **isolated antidetect profiles**, connect Playwright over a Launcher CDP endpoint instead of launching vanilla Chromium:

```bash
export MLX_TOKEN="your-bearer-token"
export MLX_FOLDER_ID="your-folder-uuid"
cdp-probe mlx --profile-id PROFILE_UUID --url https://example.com
```

```python
from playwright_cdp_probe.integrations.mlx import mlx_launch_and_probe

report = mlx_launch_and_probe(
    "profile-id",
    folder_id="folder-id",
    token="...",
    url="https://example.com",
)
print(report.exposure.score)
```

Compare `check-local` (vanilla) vs `mlx` (profile) to quantify exposure reduction — not elimination.

**Partner note (affiliate):** If Multilogin X fits your workflow (profile pools, folder scale, Launcher CDP), eligible new browser purchases may accept code **`SAAS50`** at checkout on the [official site](https://multilogin.com?a_aid=saas) — verify current terms before paying. Full disclosure: [docs/AFFILIATE.md](docs/AFFILIATE.md). Deals hub: [anti-detect.github.io](https://anti-detect.github.io/). Coupon details only via `cdp-probe --show-deal` (never printed by default).

**FAQ:** [docs/FAQ.md](docs/FAQ.md) — Playwright detection, headless Chrome, CDP exposure, antidetect comparison.




## Related tools (on PyPI)

| Package | CLI | Role |
|---------|-----|------|
| [playwright-cdp-probe](https://pypi.org/project/playwright-cdp-probe/) | `cdp-probe` | CDP / WebDriver exposure score |
| [cookie-jar-bridge](https://pypi.org/project/cookie-jar-bridge/) | `cookie-bridge` | Netscape ↔ Playwright cookies |
| [proxy-lane-checker](https://pypi.org/project/proxy-lane-checker/) | `proxy-lane` | Proxy TCP / HTTP / geo / DNSBL |
| [fingerprint-coherence](https://pypi.org/project/fingerprint-coherence/) | `fp-coherence` | UA / screen / timezone lint |

**Toolkit pipeline:** `proxy-lane check` → `fp-coherence audit` → automate → `cdp-probe run` → `cookie-bridge validate`

## License

MIT
---

**Production antidetect:** [Multilogin X](https://multilogin.com?a_aid=saas) · Code `SAAS50` (-50% browser) · [MIN50](https://multilogin.com?a_aid=saas) (-50% cloud phone)  
More scripts: [@Multilogin_Scripts_Bot](https://t.me/Multilogin_Scripts_Bot) · [Multilogin promo codes](https://anti-detect.github.io/)
