Stealth browser CLI that bypasses WAFs and bot detection
Project description
Phantom
Stealth browser CLI that bypasses WAFs and bot detection. Built on Playwright with anti-detection patches so you can fetch pages that block headless browsers, curl, and wget.
Works as a CLI tool for humans and outputs structured JSON for AI agents.
Install
pip install phantom-browse
Chromium is installed automatically on first run. To install it manually:
python -m playwright install chromium
Usage
# Get page text
phantom https://example.com
# Structured JSON output (for agents)
phantom https://example.com --json
# Screenshot
phantom https://example.com --screenshot page.png
# Login flow
phantom https://app.com/login \
--fill "input[name=email]=user@example.com" \
--fill "input[name=password]=secret" \
--click "button[type=submit]" \
--session myapp \
--json
# Reuse session (skip login next time)
phantom https://app.com/dashboard --session myapp --json
JSON Output
When using --json, Phantom returns:
{
"ok": true,
"url": "https://example.com",
"title": "Example Domain",
"text": "...",
"screenshot": null,
"console_errors": []
}
On failure:
{
"ok": false,
"url": "https://example.com",
"error": "Navigation failed: net::ERR_NAME_NOT_RESOLVED"
}
Interaction Flags
Actions execute in order, before the final page capture.
--click SELECTOR # Click element (coordinate-based, human-like timing)
--fill SEL=VAL # Fill input field (instant)
--type SEL=VAL # Type into input (80ms per-character delay)
--wait SELECTOR # Wait for element to appear
Chain them:
phantom https://app.com \
--wait "form" \
--fill "input[name=q]=test" \
--click "button[type=submit]" \
--json
Options
--json Structured JSON output
--screenshot PATH Save full-page screenshot
--session NAME Cookie persistence (~/.phantom/sessions/)
--timeout MS Navigation timeout (default: 30000)
--headless Force headless mode
--headed Force headed mode (requires display/Xvfb)
--locale LOCALE Browser locale (default: en-US)
--timezone TZ Browser timezone (default: America/New_York)
--viewport W H Viewport size (default: 1366 768)
--min-delay SECS Min seconds between requests to same domain (default: 2.0, 0 to disable)
--verbose Debug logging
What It Bypasses
Phantom bundles these anti-detection techniques:
- playwright-stealth — masks automation fingerprints
- WebDriver spoofing — hides
navigator.webdriver - Blink feature flags — disables
AutomationControlled - Realistic fingerprint — Chrome 131 User-Agent, configurable locale/timezone/viewport
- Headed mode — uses real GUI via Xvfb when available (harder to detect than headless)
- Human-like input — variable click timing, coordinate-based clicks, realistic type delays
Using With AI Agents
Phantom is designed to be called by AI agents via subprocess. The --json flag gives structured output any agent can parse:
import subprocess, json
result = subprocess.run(
["phantom", "https://example.com", "--json"],
capture_output=True, text=True
)
data = json.loads(result.stdout)
if data["ok"]:
page_text = data["text"]
Rate Limiting
Phantom enforces a 2-second per-domain cooldown by default to prevent abuse. If you call Phantom twice against the same domain in quick succession, the second call waits automatically.
phantom https://example.com --json # goes through immediately
phantom https://example.com --json # waits ~2s before requesting
phantom https://other-site.com --json # different domain, no wait
Adjust with --min-delay:
phantom https://example.com --min-delay 5 # 5s between requests (be polite)
phantom https://localhost:3000 --min-delay 0 # disable for local/owned apps
Responsible Use
Phantom is built for legitimate purposes: testing your own apps, accessing data you're authorized to retrieve, and building AI agents that browse the web respectfully.
Do:
- Test your own web applications
- Access sites and data you have permission to use
- Build agents that respect
robots.txtand rate limits - Use the default rate limiting
Don't:
- Scrape sites that prohibit it in their ToS
- Bypass authentication you're not authorized to use
- Use Phantom to overwhelm or degrade services
- Disable rate limiting against sites you don't own
The built-in rate limiter exists for a reason. If you find yourself setting --min-delay 0 against someone else's site, reconsider.
License
MIT
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 phantom_browse-0.2.0.tar.gz.
File metadata
- Download URL: phantom_browse-0.2.0.tar.gz
- Upload date:
- Size: 8.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c5067f89f402f9c9749646d693a052f7ca330b61abeb1227240adf0a1f15f0b
|
|
| MD5 |
846fa960ac0c8e97e7223f04e44769dd
|
|
| BLAKE2b-256 |
bb9f6a0d03f8e85fa7e01b707bc675321ace6e2d6df4544363e7286921534e00
|
File details
Details for the file phantom_browse-0.2.0-py3-none-any.whl.
File metadata
- Download URL: phantom_browse-0.2.0-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6db0bb2880472afca223b4950db2d76fb54d088d5416127d75594a8e32103c49
|
|
| MD5 |
573ad4d9f2629b5601d624b322e8e3e3
|
|
| BLAKE2b-256 |
97696f717f247480e49163334005a6d770498737d70b86b436503c5bd07dd473
|