Stealth web scraping when basic HTTP gets blocked — Cloudflare (Turnstile, interstitial), Akamai, Imperva, Datadome, and similar bot walls.
StealthPlex wraps the tools you'd reach for anyway — wreq, curl_cffi, cloudscraper, Scrapling, and SeleniumBase — behind a single Fetch() interface with built-in stealth: randomized browser fingerprints (User-Agent, Sec-CH-UA, Sec-Fetch-*, Accept-Language, Referer), automatic TLS/JA3 impersonation, and serial engine escalation from fast HTTP all the way to stealth browser UC/CDP automation (headed on Windows/macOS, auto-Xvfb on Linux).
from StealthPlex import Fetch
# Zero config — stealth headers + serial engine fallback
fetch = Fetch()
resp = fetch.get("https://protected-site.com")
print(resp.text) # HTML
print(resp.json()) # or JSON
print(resp.engine) # which engine bypassedFallback chain: curl_cffi → wreq → cloudscraper → scrapling → seleniumbase
Each request gets randomized stealth fingerprints. If one engine gets blocked, the next one takes over automatically.
StealthPlex core has no default engine dependencies to remain lightweight. You must install at least one engine extra to perform requests.
Using uv:
uv add StealthPlex --extra allUsing pip:
pip install "StealthPlex[all]"Using uv:
uv add StealthPlex --extra wreqUsing pip:
pip install "StealthPlex[wreq]"Using uv:
uv add StealthPlex --extra curl_cffiUsing pip:
pip install "StealthPlex[curl_cffi]"Using uv:
uv add StealthPlex --extra cloudscraperUsing pip:
pip install "StealthPlex[cloudscraper]"Using uv:
uv add StealthPlex --extra scraplingUsing pip:
pip install "StealthPlex[scrapling]"Using uv:
uv add StealthPlex --extra seleniumbaseUsing pip:
pip install "StealthPlex[seleniumbase]"Using uv:
uv add StealthPlex --extra curl_cffi --extra seleniumbaseUsing pip:
pip install "StealthPlex[curl_cffi,seleniumbase]"Because anti-bot protections change constantly, you should keep all engine packages updated to their latest versions:
Using uv:
uv add --upgrade "StealthPlex[all]"Using pip (requires --upgrade-strategy eager to force upgrade of all extra engines):
pip install --upgrade --upgrade-strategy eager "StealthPlex[all]"| Engine | Extra | Layer | Upstream | Detailed Docs |
|---|---|---|---|---|
wreq |
wreq |
L1 | 0x676e67/wreq-python | wreq Guide |
curl_cffi |
curl_cffi |
L1 | lexiforest/curl_cffi | curl_cffi Guide |
cloudscraper |
cloudscraper |
L2 | VeNoMouS/cloudscraper | cloudscraper Guide |
scrapling |
scrapling |
L3 | D4Vinci/Scrapling | scrapling Guide |
seleniumbase |
seleniumbase |
L4 | seleniumbase/SeleniumBase | seleniumbase Guide |
Just call Fetch() — no engine needed. StealthPlex injects stealth headers and walks the engine chain serially until one bypasses.
from StealthPlex import Fetch
fetch = Fetch()
# GET with full stealth headers auto-injected
resp = fetch.get("https://httpbin.org/get")
print(resp.status_code)
print(resp.text) # raw HTML/text
print(resp.json()) # auto-parse JSON
print(resp.engine) # "wreq", "curl_cffi", etc.
print(resp.attempts) # ("wreq",) or ("wreq", "curl_cffi")
print(resp.ok) # True if status < 400from StealthPlex import Fetch
fetch = Fetch()
resp = fetch.post(
"https://httpbin.org/post",
json={"username": "admin", "password": "secret"},
headers={"X-Custom": "value"},
)
print(resp.json())from StealthPlex import Fetch
fetch = Fetch()
# PUT with raw data
resp = fetch.put("https://httpbin.org/put", data="update payload")
print(resp.json())
# DELETE
resp = fetch.delete("https://httpbin.org/delete")
print(resp.status_code)
# PATCH with JSON
resp = fetch.patch("https://httpbin.org/patch", json={"key": "val"})
print(resp.json())
# HEAD (status + headers only)
resp = fetch.head("https://httpbin.org/get")
print(resp.status_code, resp.headers)
# OPTIONS
resp = fetch.options("https://httpbin.org/get")
print(resp.status_code)from StealthPlex import Fetch
fetch = Fetch()
# All parameters work with full IDE autocomplete
resp = fetch.get(
"https://httpbin.org/get",
headers={"Authorization": "Bearer token123"},
cookies={"session": "abc123"},
params={"q": "stealth scraping", "page": "1"},
timeout=30.0,
allow_redirects=False, # or redirect=False
)
print(resp.status_code)
print(resp.json())from StealthPlex import Fetch
# Only try these two engines in this order
fetch = Fetch(fallback=["curl_cffi", "cloudscraper"])
resp = fetch.get("https://example.com")
print(resp.engine)For full upstream API access (types, autocomplete, docs), bind to a specific engine:
import asyncio
from StealthPlex import Fetch
async def main():
fetch = Fetch(engine="wreq")
response = await fetch.get("https://example.com", emulation=fetch.Emulation.Firefox149)
print(await response.text())
asyncio.run(main())from StealthPlex import Fetch
fetch = Fetch(engine="curl_cffi")
response = fetch.get("https://example.com", impersonate="chrome124")
print(response.text)from StealthPlex import Fetch
fetch = Fetch(engine="cloudscraper")
scraper = fetch.create_scraper(browser="chrome")
response = scraper.get("https://example.com")
print(response.text)from StealthPlex import Fetch
fetch = Fetch(engine="scrapling")
response = fetch.fetcher.fetch("https://example.com")
print(response.text)from StealthPlex import Fetch
fetch = Fetch(engine="seleniumbase")
with fetch.SB(uc=True) as sb:
sb.activate_cdp_mode("https://example.com")
sb.sleep(2.0)
print(sb.get_page_source())| Need | Use | Docs |
|---|---|---|
| Stealth auto-bypass (recommended) | Fetch() |
— |
| Custom engine order | Fetch(fallback=["wreq", "curl_cffi"]) |
— |
| Full wreq API | Fetch(engine="wreq") |
Guide |
| Full curl_cffi API | Fetch(engine="curl_cffi") |
Guide |
| Full cloudscraper API | Fetch(engine="cloudscraper") |
Guide |
| Adaptive fetch (Scrapling) | Fetch(engine="scrapling") |
Guide |
| Full SeleniumBase API | Fetch(engine="seleniumbase") |
Guide |
| Shortcuts | curl_fetch(), wreq_fetch(), cloudscraper_fetch(), scrapling_fetch(), seleniumbase_fetch() |
— |
