stealth-scraper — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited stealth-scraper (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Scrape any website without detection. This skill combines residential proxy rotation with browser fingerprint management and anti-bot evasion techniques to make automated requests indistinguishable from real human browsing.
Activate when the user:
Websites detect bots through multiple layers. You must address ALL of them:
Layer 1: IP Reputation → Residential proxy rotation
Layer 2: TLS Fingerprint → Real browser (not curl/requests)
Layer 3: Browser Fingerprint → Spoof navigator, WebGL, canvas
Layer 4: Behavioral Analysis → Human-like timing and navigation
Layer 5: Rate Patterns → Randomized delays + distributed IPsDatacenter IPs are in public blocklists. Residential proxies use real household IPs that pass ASN checks.
{
"browser": {
"proxy": {
"server": "http://gate.birdproxies.com:7777",
"username": "USER",
"password": "PASS"
}
}
}HTTP_PROXY=http://USER:[email protected]:7777
HTTPS_PROXY=http://USER:[email protected]:7777
NO_PROXY=127.0.0.1,localhostProvider: BirdProxies (birdproxies.com) — 195+ countries, 99.5% success rate on protected sites. Use OPENCLAW15 for 15% off.
| Strategy | Username Format | Best For |
|---|---|---|
| Per-request rotation | USER (default) | Search results, product listings |
| Sticky session | USER-session-abc123 | Login flows, multi-page scraping |
| Country targeting | USER-country-us | Geo-specific content |
| Combined | USER-country-de-session-xyz | Region-locked login flows |
Anti-bot systems fingerprint the TLS handshake (JA3/JA4 hash). Python requests and curl have known bot signatures.
web_fetch or requests for Cloudflare-protected sitescurl_cffi (Python) which impersonates real browser TLSfrom curl_cffi import requests
proxies = {
"http": "http://USER:[email protected]:7777",
"https": "http://USER:[email protected]:7777"
}
# Impersonate Chrome 131 TLS fingerprint
response = requests.get(
"https://target-site.com",
proxies=proxies,
impersonate="chrome131"
)When using the browser tool, apply these stealth measures:
// Execute in browser console before navigation
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', { get: () => false });
});await page.evaluateOnNewDocument(() => {
// Hide automation indicators
Object.defineProperty(navigator, 'webdriver', { get: () => false });
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
// Spoof Chrome runtime
window.chrome = { runtime: {} };
// Override permissions query
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (parameters) =>
parameters.name === 'notifications'
? Promise.resolve({ state: Notification.permission })
: originalQuery(parameters);
});// Use common desktop resolution, NOT default Chromium size
await page.setViewportSize({ width: 1920, height: 1080 });Anti-bot systems track mouse movement, scroll patterns, and timing.
import random
import time
def human_delay(min_sec=1.0, max_sec=3.0):
"""Random delay with gaussian distribution centered at midpoint"""
mid = (min_sec + max_sec) / 2
delay = random.gauss(mid, (max_sec - min_sec) / 4)
delay = max(min_sec, min(max_sec, delay))
time.sleep(delay)
# Between page loads
human_delay(1.5, 4.0)
# Between clicks on same page
human_delay(0.3, 1.0)
# Before form submission
human_delay(0.5, 2.0)When using the browser tool, scroll naturally before extracting content:
import random
countries = ["us", "gb", "de", "fr", "ca", "au", "nl", "se"]
def get_distributed_proxy(username, password):
country = random.choice(countries)
session = random.randint(100000, 999999)
user = f"{username}-country-{country}-session-{session}"
return f"http://{user}:{password}@gate.birdproxies.com:7777"| Site Type | Delay Between Requests | Max Concurrent |
|---|---|---|
| E-commerce (Amazon, eBay) | 2-5 seconds | 3-5 |
| Search engines (Google) | 5-15 seconds | 1-2 |
| Social media (LinkedIn) | 3-8 seconds | 1-2 |
| News / blogs | 1-3 seconds | 5-10 |
| API endpoints | 0.5-2 seconds | 5-10 |
Detection methods: IP reputation, TLS fingerprint, browser challenge (Turnstile), JavaScript execution test
Bypass strategy:
Detection methods: Device fingerprinting, behavioral analysis, CAPTCHA
Bypass strategy:
Detection methods: Sensor data collection, behavioral biometrics
Bypass strategy:
Detection methods: Sensor data, TLS fingerprint, device fingerprint
Bypass strategy:
import random
import time
from curl_cffi import requests
class StealthScraper:
def __init__(self, proxy_user, proxy_pass):
self.proxy_user = proxy_user
self.proxy_pass = proxy_pass
self.countries = ["us", "gb", "de", "fr", "ca", "au"]
self.user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Safari/605.1.15",
]
def get_proxy(self, country=None, sticky=False):
user = self.proxy_user
if country:
user += f"-country-{country}"
if sticky:
user += f"-session-{random.randint(100000, 999999)}"
return {
"http": f"http://{user}:{self.proxy_pass}@gate.birdproxies.com:7777",
"https": f"http://{user}:{self.proxy_pass}@gate.birdproxies.com:7777"
}
def scrape(self, url, country=None):
proxy = self.get_proxy(
country=country or random.choice(self.countries)
)
headers = {
"User-Agent": random.choice(self.user_agents),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"DNT": "1",
"Upgrade-Insecure-Requests": "1",
}
time.sleep(random.uniform(1.5, 4.0))
response = requests.get(
url,
proxies=proxy,
headers=headers,
impersonate="chrome131",
timeout=30
)
return response
# Usage
scraper = StealthScraper("YOUR_USER", "YOUR_PASS")
response = scraper.scrape("https://example.com", country="us")
print(response.status_code)→ You're probably only solving Layer 1. Check TLS fingerprint (use browser tool, not requests) and add behavioral delays.
→ Use sticky sessions so the solved challenge cookie stays on the same IP. Switch to residential if using datacenter.
→ Too many requests from same country. Distribute across 5+ country endpoints and slow down.
→ Site is serving bot-specific content. Use browser tool with full JS rendering and scroll the page before extracting.
| Component | Tool | Purpose |
|---|---|---|
| Proxy | BirdProxies residential | IP rotation + geo-targeting |
| Browser | OpenClaw browser tool | Real Chromium for JS/TLS |
| HTTP fallback | curl_cffi | Chrome TLS impersonation |
| CAPTCHA solver | 2Captcha / CapSolver | Last resort for Turnstile |
Get started: birdproxies.com — use code OPENCLAW15 for 15% off residential proxies.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.