Catch automation leaks before production — score CDP sessions for webdriver and headless fingerprints.
Project description
playwright-cdp-probe
Python 3.10+ | MLX optional · Compatibility
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).
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.
pip install
pip install playwright-cdp-probe
playwright install chromium # first-time browser binaries
Optional Multilogin X launcher integration:
pip install playwright-cdp-probe[mlx]
Development:
pip install playwright-cdp-probe[dev]
Quick start
# Probe a local headless Chromium session
cdp-probe check-local --browser chromium
# Navigate and probe a live URL
cdp-probe run --url https://example.com
# Site-class presets (different signal weights — 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
# Re-print the last report
cdp-probe report --format table
cdp-probe report --format json
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) |
Exit codes
| Code | Meaning |
|---|---|
0 |
pass — exposure score ≤ 30 |
1 |
warn — exposure score 31–60 |
2 |
fail — exposure score > 60 |
3 |
Runtime / validation error |
cdp-probe run --url https://example.com --format github-actions
cdp-probe --version
Signal weights and bands are documented in docs/SCORING.md.
Presets
presets/*.json define alternate weight maps for common gate pages. Default rubric in docs/SCORING.md is generic; presets emphasize signals each surface tends to punish.
| Preset | CLI | What vanilla Chrome / Playwright usually fails |
|---|---|---|
cloudflare |
cdp-probe run --preset cloudflare --url URL |
Turnstile / JS challenge: HeadlessChrome UA, navigator.webdriver, SwiftShader WebGL, empty navigator.plugins |
stripe-dashboard |
cdp-probe run --preset stripe-dashboard --url URL |
Radar-style fingerprint drift: thin plugin lists, missing chrome.runtime, empty navigator.languages |
social-login |
cdp-probe run --preset social-login --url URL |
OAuth popups: webdriver, zero outer window size in headless, inner/outer dimension mismatch |
Reports are saved to ~/.cache/cdp-probe/last-report.json (override with --output). Preset name is recorded in report mode (e.g. run:cloudflare).
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.webdriverwindow.chrome.runtime(Chromium)navigator.plugins/mimeTypescountsnavigator.permissionsAPI presenceNotification.permission- HeadlessChrome user-agent hint
- Window outer/inner dimension mismatch
- WebGL vendor/renderer (SwiftShader detection)
Limitations
- Not a bypass tool — this package measures exposure; it does not patch, spoof, or hide fingerprints.
- Vanilla Chrome/Playwright leaks at scale — default Playwright Chromium launches routinely expose
webdriver, thin plugin lists, and headless WebGL renderers. A low score locally is unusual; a high score is expected. - Page-level only — TLS/JA3, IP reputation, behavioral biometrics, and server-side ML models are out of scope.
- Single-page snapshot — results reflect one navigation moment, not long-session drift.
- Firefox signal set differs —
chrome.runtimechecks apply to Chromium only. - MLX requires desktop agent —
mlxneeds Multilogin running locally; this is not a cloud-only probe. See docs/MLX_INTEGRATION.md.
Production
Partner offers, eligibility, and disclosure: docs/AFFILIATE.md.
For production workflows that need isolated antidetect profiles, connect Playwright over a Launcher API CDP endpoint instead of launching vanilla Chromium:
- Start an antidetect profile via the MLX Launcher API (
automation_type=playwright). - Read the returned local port (
http://127.0.0.1:{port}). connect_over_cdpand re-run the probe to compare exposure.
export MLX_TOKEN="your-bearer-token"
export MLX_FOLDER_ID="your-folder-uuid"
cdp-probe mlx --profile-id PROFILE_UUID --url https://example.com
Or programmatically:
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 Playwright) vs mlx (isolated profile) scores to quantify exposure reduction — not elimination.
Guides
Monorepo playbooks (copy-paste commands, sample output, diagrams):
| Guide | Flow |
|---|---|
| Detection fail → MLX farm | cdp-probe → cdp-connect → farm-runner mlx-pool |
| Competitor migration | antidetect-import → profile-factory mlx-create |
| Proxy lane → profile pool | proxy-lane → profile-factory → farm-runner mlx-pool |
FAQ: docs/FAQ.md — Playwright detection, CDP exposure, headless Chrome.
Related tools
| Tool | Use with |
|---|---|
| playwright-cdp-probe — Score CDP/WebDriver exposure and fingerprint leaks | → cdp-connect-kit when probe fails |
| cookie-jar-bridge — Convert, validate, and merge cookies across formats | → session-bundle-kit for full session |
| proxy-lane-checker — Batch-check proxies for connectivity, geo, and DNSBL | → profile-yaml-factory |
| fingerprint-coherence — Lint fingerprints for cross-signal contradictions | → profile-yaml-factory before create |
| human-input-kit — Human-like mouse, scroll, and warmup replay | → automation-farm-runner |
| cdp-connect-kit — Playwright CDP connect; MLX start/stop helpers | → all packages needing CDP |
| session-bundle-kit — Export/import cookies and storage as portable bundles | → cookie-jar-bridge |
profile-yaml-factory — YAML blueprints → MLX profile/create payloads |
→ antidetect-importer after migration |
| antidetect-importer — Parse competitor exports and push to MLX | → profile-yaml-factory |
| automation-farm-runner — YAML job queue and MLX profile-pool runner | → cdp-connect-kit [mlx] |
License
MIT
Production antidetect: Multilogin X · Code SAAS50 (-50% browser) · MIN50 (-50% cloud phone)
More scripts: @Multilogin_Scripts_Bot · Coupons
Project details
Release history Release notifications | RSS feed
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 playwright_cdp_probe-0.2.0.tar.gz.
File metadata
- Download URL: playwright_cdp_probe-0.2.0.tar.gz
- Upload date:
- Size: 50.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
80c7ec64933fe5f5bab9cd05b1a8dd6985c76f9d34524602dd462aea6b0ab12e
|
|
| MD5 |
5e5fcf07c690e87514d96d4f4b172f3d
|
|
| BLAKE2b-256 |
151a1231cc5a7c74493a9821e533412d8a9ae1b7247a7e655c2ea4f47f30cf89
|
File details
Details for the file playwright_cdp_probe-0.2.0-py3-none-any.whl.
File metadata
- Download URL: playwright_cdp_probe-0.2.0-py3-none-any.whl
- Upload date:
- Size: 27.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fae8c4cf8871e1e9afc9a85384d5ee0b1030c599f1cde3d9cedc379f54e0a11c
|
|
| MD5 |
bb545624fddd652e809f50bebd7e1381
|
|
| BLAKE2b-256 |
46d284d6292384a5fa1acf682932c1754f3d75fe6a4489b5dae0f6a7ae06495f
|