Stealth web scraping SDK with optional cloud browser support
Project description
Abrasio SDK
Undetected web scraping SDK inspired on Patchright with human-like behavior simulation and optional cloud browser support.
Features
| Feature | Description |
|---|---|
| Undetected | Patchright bypasses Runtime.enable and CDP detection |
| Free Local Mode | Run on your machine with anti-detection patches |
| Cloud Mode | Real fingerprints(paid) |
| Human Behavior | Bezier mouse movements, natural typing, smooth scrolling |
| TLS Fingerprinting | curl_cffi for JA3/JA4 TLS fingerprint matching |
| Fingerprint Config | Control WebGL, WebRTC, canvas/audio noise per session |
| Playwright API | Same API you already know |
Anti-Detection Status
| Technique | Status | Notes |
|---|---|---|
| Patchright (CDP leak) | Implemented | Protocol-level, not JS patches |
| navigator.webdriver | Implemented | --disable-blink-features=AutomationControlled |
| Headless User-Agent fix | Implemented | Auto-removes "HeadlessChrome" in headless mode |
| Human behavior (Bezier) | Implemented | Mouse, typing, scrolling |
| TLS fingerprinting (JA3/JA4) | Implemented | via curl_cffi for HTTP requests |
| Canvas noise | Implemented | Optional via FingerprintConfig(canvas_noise=True) |
| Audio noise | Implemented | Optional via FingerprintConfig(audio_noise=True) |
| WebRTC IP leak protection | Implemented | Via FingerprintConfig(webrtc=False) |
| WebGL control | Implemented | Enabled by default, disable via config |
| Timezone/Locale consistency | Auto-validated | Auto-configures from region or IP |
| Retry on rate limit | Implemented | Exponential backoff with Retry-After |
Table of Contents
- Installation
- Quick Start
- FingerprintConfig
- Human-Like Behavior
- TLS Fingerprinting (HTTP)
- Configuration
- Cloud Mode
- Error Handling
- API Reference
- Best Practices
Installation
# Install SDK
pip install abrasio
# Install real Chrome (NOT Chromium) for maximum stealth
patchright install chrome
# Optional: TLS fingerprinting for HTTP requests
pip install abrasio[tls]
# Optional: fingerprint generation utilities
pip install abrasio[fingerprint]
# Install everything
pip install abrasio[all]
Requirements
- Python 3.8+
- Chrome browser (installed via
patchright install chrome)
Quick Start
Local Mode (Free)
import asyncio
from abrasio import Abrasio
async def main():
async with Abrasio(headless=False) as browser:
page = await browser.new_page()
await page.goto("https://example.com")
print(await page.title())
asyncio.run(main())
Cloud Mode (Paid)
import asyncio
from abrasio import Abrasio
async def main():
async with Abrasio(
api_key="sk_live_xxx",
region="BR",
url="https://example.com.br",
) as browser:
page = await browser.new_page()
await page.goto("https://example.com.br")
print(await page.title())
asyncio.run(main())
Synchronous API
from abrasio.sync_api import Abrasio
with Abrasio(headless=False) as browser:
page = browser.new_page()
page.goto("https://example.com")
print(page.title())
FingerprintConfig
Control browser fingerprint protections in local mode only. In cloud mode, the cloud browser handles all fingerprinting automatically.
from abrasio import Abrasio, FingerprintConfig
async with Abrasio(
headless=False,
fingerprint=FingerprintConfig(
webgl=True, # Keep WebGL enabled (default). False blocks it.
webrtc=False, # Block WebRTC IP leak (recommended with proxy)
canvas_noise=True, # Add noise to canvas fingerprint
audio_noise=True, # Add noise to audio fingerprint
),
) as browser:
page = await browser.new_page()
await page.goto("https://example.com")
| Option | Default | Description |
|---|---|---|
webgl |
True |
Enable WebGL APIs. Disabling is a strong bot signal. |
webrtc |
True |
Enable WebRTC. Set False with proxy to prevent real IP leak. |
canvas_noise |
False |
Add imperceptible noise to canvas reads. Randomizes fingerprint. |
audio_noise |
False |
Add noise to AudioContext reads. Randomizes fingerprint. |
Cloud mode:
FingerprintConfigis completely ignored. The cloud browser uses real collected fingerprints
Human-Like Behavior
Utilities for simulating realistic human behavior to bypass behavioral analysis.
Mouse Movement (Bezier Curves)
from abrasio.utils import human_move_to, human_click
# Move mouse with natural Bezier curve trajectory
await human_move_to(page, x=500, y=300)
# Click with natural movement and random offset
await human_click(page, "button#submit")
Natural Typing
from abrasio.utils import human_type
await human_type(
page,
"Hello, World!",
selector="input#search",
mistake_probability=0.02,
think_pause_probability=0.05,
)
Smooth Scrolling
from abrasio.utils import human_scroll, simulate_reading
await human_scroll(page, "down", amount=400, smooth=True)
await simulate_reading(page, min_seconds=3, max_seconds=8)
All Utilities
from abrasio.utils import (
human_move_to, # Bezier curve mouse movement
human_click, # Natural click with movement
human_type, # Variable-speed typing with mistakes
human_scroll, # Smooth scrolling with momentum
human_wait, # Random wait (skewed distribution)
random_delay, # Simple random delay
simulate_reading, # Simulate page reading behavior
)
TLS Fingerprinting (HTTP)
For HTTP requests outside the browser, use StealthClient which matches real browser TLS fingerprints via curl_cffi.
pip install abrasio[tls]
from abrasio.http import StealthClient
# Async
async with StealthClient() as client:
response = await client.get("https://example.com")
print(response.text)
# With region (auto-sets Accept-Language)
async with StealthClient(region="BR") as client:
response = await client.get("https://example.com.br")
# With proxy
async with StealthClient(proxy="http://user:pass@host:8080") as client:
response = await client.get("https://example.com")
# Rotate browser version on each request
async with StealthClient(rotate_impersonation=True) as client:
for url in urls:
response = await client.get(url)
Configuration
AbrasioConfig
from abrasio import Abrasio, AbrasioConfig, FingerprintConfig
config = AbrasioConfig(
# Mode: None = local (free), "sk_xxx" = cloud (paid)
api_key=None,
# Browser
headless=False, # Visible = more stealthy
proxy="http://user:pass@host:8080",
timeout=30000,
# Region (auto-configures locale/timezone)
region="BR",
# Fingerprint (local mode only)
fingerprint=FingerprintConfig(
webgl=True,
webrtc=False,
canvas_noise=True,
audio_noise=True,
),
# Profile persistence
user_data_dir="./my_profile",
# Cloud mode
profile_id="my-profile",
# Advanced
extra_args=[],
debug=False,
)
async with Abrasio(config) as browser:
...
Region Auto-Configuration
config = AbrasioConfig(region="BR")
# locale="pt-BR", timezone="America/Sao_Paulo"
config = AbrasioConfig(region="JP")
# locale="ja-JP", timezone="Asia/Tokyo"
50+ regions supported. If you set a mismatched timezone, you'll get a warning:
config = AbrasioConfig(region="BR", timezone="America/New_York")
print(config.region_warnings)
# ['Timezone mismatch: using America/New_York but region BR expects America/Sao_Paulo']
Without explicit region, locale/timezone are auto-detected from your public IP.
Environment Variables
| Variable | Description | Default |
|---|---|---|
ABRASIO_API_KEY |
API key for cloud mode | None |
ABRASIO_API_URL |
API base URL | https://abrasio.scrapetechnology.com/ |
Cloud Mode (Paid)
With an API key, you get access to the Abrasio cloud infrastructure:
| Feature | Description |
|---|---|
| Real Fingerprints | collected device data |
| Geo-Targeting | Target specific countries/regions |
| Persistent Profiles | Maintain cookies and history across sessions |
| Session Recording | Playwright trace recording for debugging |
| Live View | Real-time browser streaming via noVNC |
| Automatic Retry | SDK retries on rate limit (429) with backoff |
from abrasio import Abrasio
async with Abrasio(
api_key="sk_live_xxx",
region="BR",
url="https://target-site.com.br",
profile_id="my-profile",
) as browser:
page = await browser.new_page()
# Live view URL (if enabled on server)
if browser.live_view_url:
print(f"Watch live: {browser.live_view_url}")
await page.goto("https://target-site.com.br")
print(await page.title())
Error Handling
from abrasio import (
Abrasio,
AbrasioError, # Base error
AuthenticationError, # Invalid API key (401)
InsufficientFundsError, # Not enough balance (402)
RateLimitError, # Too many sessions (429) - auto-retried
SessionError, # Session creation/management error
BrowserError, # Browser operation error
TimeoutError, # Operation timeout
BlockedError, # Target site blocked request
)
try:
async with Abrasio(api_key="sk_live_xxx") as browser:
page = await browser.new_page()
await page.goto("https://example.com")
except AuthenticationError:
print("Invalid API key")
except InsufficientFundsError as e:
print(f"Add funds. Balance: ${e.balance:.2f}")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
except SessionError as e:
print(f"Session error: {e.message}")
except AbrasioError as e:
print(f"Error: {e.message}")
Note: The SDK automatically retries on 429 (rate limit), 502, 503, 504 with exponential backoff up to 3 times.
API Reference
Abrasio
class Abrasio:
def __init__(
self,
config: Optional[AbrasioConfig] = None,
*,
api_key: Optional[str] = None,
headless: bool = True,
proxy: Optional[str] = None,
stealth: bool = True,
**kwargs,
): ...
async def start(self) -> "Abrasio": ...
async def close(self) -> None: ...
async def new_page(self) -> Page: ...
async def new_context(self, **kwargs) -> BrowserContext: ...
@property
def browser(self): ... # Browser (cloud) or BrowserContext (local)
@property
def is_cloud(self) -> bool: ...
@property
def is_local(self) -> bool: ...
@property
def live_view_url(self) -> Optional[str]: ... # Cloud mode only
Human Utilities
async def human_move_to(page, x, y, *, min_time=0.1, max_time=1.5): ...
async def human_click(page, selector=None, *, offset_range=5, move_first=True): ...
async def human_type(page, text, selector=None, *, mistake_probability=0.02): ...
async def human_scroll(page, direction="down", amount=None, *, smooth=True): ...
async def random_delay(min_ms=100, max_ms=500): ...
async def human_wait(min_seconds=0.5, max_seconds=2.0): ...
async def simulate_reading(page, min_seconds=2.0, max_seconds=8.0): ...
StealthClient (TLS)
from abrasio.http import StealthClient, BrowserImpersonation
class StealthClient:
def __init__(self, impersonate=BrowserImpersonation.DEFAULT,
proxy=None, region=None, rotate_impersonation=False): ...
async def get(self, url, **kwargs) -> StealthResponse: ...
async def post(self, url, **kwargs) -> StealthResponse: ...
Best Practices
- Headless mode is safe — SDK automatically removes "HeadlessChrome" from User-Agent
- Don't set
user_agent— let the SDK handle it (auto-fixed in headless mode) - Don't set
viewport— usesno_viewportfor realistic behavior - Add human behavior between actions (
human_wait,human_click) - Use persistent profiles with
user_data_dirfor cookie persistence - Use
regionto auto-configure locale/timezone consistently - Set
webrtc=Falsewhen using a proxy (prevents IP leak) - Test against bot detection sites before production deployment
Testing Anti-Detection
import asyncio
from abrasio import Abrasio
async def test():
async with Abrasio(headless=False) as browser:
page = await browser.new_page()
await page.goto("https://bot.sannysoft.com/")
await page.screenshot(path="sannysoft.png")
await page.goto("https://abrahamjuliot.github.io/creepjs/")
await page.wait_for_timeout(5000)
await page.screenshot(path="creepjs.png")
asyncio.run(test())
Project Structure
abrasio-sdk/
├── abrasio/
│ ├── __init__.py # Public API exports
│ ├── _api.py # Abrasio class (local + cloud)
│ ├── _config.py # AbrasioConfig, FingerprintConfig
│ ├── _exceptions.py # Exception hierarchy
│ ├── local/
│ │ └── browser.py # StealthBrowser (Patchright)
│ ├── cloud/
│ │ ├── browser.py # CloudBrowser (API + CDP)
│ │ └── api_client.py # HTTP client with retry
│ ├── http/
│ │ └── client.py # StealthClient (curl_cffi TLS)
│ ├── sync_api/
│ │ └── _sync.py # Synchronous wrapper
│ └── utils/
│ ├── human.py # Human behavior simulation
│ ├── fingerprint.py # Region config, validation
│ └── geolocation.py # IP-based locale detection
├── examples/
│ ├── basic_local.py # Local mode example
│ ├── basic_cloud.py # Cloud mode example
│ ├── human_behavior.py # Human behavior demo
│ ├── fingerprint_check.py # Fingerprint validation
│ └── tls_fingerprint.py # TLS fingerprinting
├── docs/ # Documentation
└── pyproject.toml
References
- Patchright - Undetected Playwright fork
- curl_cffi - TLS fingerprinting HTTP client
- BrowserForge - Fingerprint generation
- Ghost Cursor - Bezier curve mouse movements
License
Proprietary - Scrape Technology
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 abrasio-0.1.1.tar.gz.
File metadata
- Download URL: abrasio-0.1.1.tar.gz
- Upload date:
- Size: 814.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5e9e32174c1633a0f21dd2151e9125e4418c7739adb81c246f157436f64c39c
|
|
| MD5 |
f1669f7dd3651782220a912c96d07977
|
|
| BLAKE2b-256 |
0229da18b47fb1a3b657882e073a962c70d50928ff056a7777464190d79fa263
|
File details
Details for the file abrasio-0.1.1-py3-none-any.whl.
File metadata
- Download URL: abrasio-0.1.1-py3-none-any.whl
- Upload date:
- Size: 50.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3135cd25da7a94e93262e288229ecbe60f95021e2724a67b77bf56dca9d3903d
|
|
| MD5 |
90cc7a4263f403bb0f50dc9d7009347d
|
|
| BLAKE2b-256 |
b2340d46a8da70ab6015a6c2d01f26f0979961afc5276296a7a2a6d7c983c6d7
|