autoreg-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok60915d52e8425
2026-10-20 02:16:32 +03:00
commit f58eafeb48
565 changed files with 60064 additions and 0 deletions

View File

@@ -0,0 +1,196 @@
---
name: cloudflare-bypass-scraping
description: Scrape Cloudflare sites. curl_cffi or full browser bypass.
category: automation
version: 1.0.0
author: ENI/Gothbreach
license: MIT
---
# Cloudflare Bypass for Web Scraping
## When to Use
- Target website returns Cloudflare "Checking your browser" or "Attention Required" interstitial
- Standard `requests`/`httpx` gets 403 or empty response from a CF-protected site
- Need to scrape emails, data, or content from sites behind Cloudflare
- Single-page or multi-page crawling with CF bypass
Two-tier approach for scraping websites protected by Cloudflare:
| Tier | Tool | When | Overhead |
|------|------|------|----------|
| 1 — Lightweight | `curl_cffi` + `impersonate="chrome124"` | 90% of sites (TLS fingerprint check only) | Zero — pure HTTP |
| 2 — Full browser | CloudflareBypassForScraping server (CloakBrowser) | Sites with full JS challenge / Turnstile | 535 MB Chromium download, ~500 MB RAM |
## Tier 1: curl_cffi (use first, works now)
`curl_cffi` impersonates Chrome's TLS/JA3 fingerprint at the HTTP library level. No browser, no JS engine — just TLS mimicry. Handles the "Checking your browser" interstitial on most CF-protected sites.
```python
from curl_cffi import requests
resp = requests.get(
"https://protected-site.com",
impersonate="chrome124", # Chrome 124 TLS fingerprint
timeout=30,
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
},
)
html = resp.text
```
**Install**: `pip install curl_cffi`
**Limitations**: Does NOT execute JavaScript. Sites with Turnstile widget or full "5-second challenge" page will still block. Fall back to Tier 2.
## Tier 1.5: Headless-Chrome fetch bridge (когда curl_cffi бессилен)
**Симптом:** API возвращает «invalid api key»/403/пустой ответ из curl, curl_cffi (ВСЕ impersonate-профили: chrome/chrome124/chrome131/safari/edge99), python requests — но тот же ключ через `fetch()` в реальном Chrome работает. IP одинаковый, заголовки не влияют. Значит backend сверяет JA3/TLS строже, чем умеет curl_cffi (проверено live: beta.pvacodes.com, 2026-09-19).
**Решение:** локальный HTTP-мост, проксирующий запросы через `page.evaluate(fetch)` в headless Chrome:
```python
# pva_bridge.py — рабочий паттерн (Desktop/jiofarm_pva/pva_bridge.py)
# Playwright worker-поток + queue (greenlet-safe), ThreadingHTTPServer на 127.0.0.1
from playwright.sync_api import sync_playwright
# ВАЖНО: launch(headless=True, channel="chrome") БЕЗ доп. args и БЕЗ new_context(locale=...) —
# «чистый» launch прошёл TLS-гейт, а версия с --disable-blink-features и locale=en-US — нет.
# page.goto(origin) один раз, дальше page.evaluate(JS_FETCH, url) где
# JS_FETCH = "async (url) => { const r = await fetch(url, {credentials:'include'}); return await r.text(); }"
```
**Greenlet-ловушка (обязательно):** playwright sync_api НЕЛЬЗЯ вызывать из потоков ThreadingHTTPServer — «Cannot switch to a different thread». Паттерн: один daemon-worker владеет page, HTTP-handler кладёт `(payload, result_box, threading.Event)` в `queue.Queue` и ждёт `event.wait(90)`.
**Диагностика:** если bridge отдаёт «api key inactive» хотя тест-скрипт работает — diff launch-параметров и проверь, что ключ в файле не замаскирован (см. masking pitfall в `ai-provider-autoreg`).
Когда bridge нужен с залогиненной сессией (дашборд-скрап) — добавь автологин (fill email/password + submit + `wait_for_selector(visible)` из-за CSS fade-in) и `credentials:'include'` в fetch.
## Tier 2: CloudflareBypassForScraping Server
Full Chromium browser (CloakBrowser — stealth-patched Chromium 146) that solves the JS challenge, then caches `cf_clearance` cookies. Subsequent requests are instant.
**Repo**: `https://github.com/sarperavci/CloudflareBypassForScraping` (2.5k stars, MIT)
### Setup
```bash
git clone https://github.com/sarperavci/CloudflareBypassForScraping.git
cd CloudflareBypassForScraping
pip install -r server_requirements.txt
```
### ⚠️ Hermes PYTHONPATH pitfall
Hermes sets `PYTHONPATH` to the old `hermes-agent-0.18.2-latest` venv which has playwright files locked (PermissionError). The CF bypass server needs playwright. **Always run with `PYTHONPATH=` cleared:**
```bash
PYTHONPATH= python server.py --port 8000
```
First run downloads CloakBrowser Chromium (~535 MB) from GitHub releases. This takes 5-10 minutes. Subsequent starts are instant.
### Run
```bash
cd CloudflareBypassForScraping
PYTHONPATH= python server.py --port 8000 --log-level info
```
### API Endpoints
**`/html` — Get rendered HTML after CF bypass:**
```bash
curl "http://localhost:8000/html?url=https://nopecha.com/demo/cloudflare"
```
**`/cookies` — Get cf_clearance cookies only:**
```bash
curl "http://localhost:8000/cookies?url=https://protected-site.com"
# Returns: {"cookies": {"cf_clearance": "..."}, "user_agent": "..."}
```
**Mirror mode — proxy any request through the server:**
```bash
curl "http://localhost:8000/api/data" \
-H "x-hostname: protected-site.com" \
-H "x-proxy: http://user:pass@proxy:port" # optional upstream proxy
```
### Control headers
| Header | Purpose |
|--------|---------|
| `x-hostname` | Target hostname (required) |
| `x-proxy` | Upstream proxy URL (optional) |
| `x-bypass-cache` | Set to `true` to force fresh cookie generation |
### Docker (alternative)
```bash
docker compose pull && docker compose up -d
```
## Integration pattern: email scraper
See `templates/email_scraper_cf.py` for a complete example that:
- Tries `curl_cffi` first (Tier 1)
- Falls back to CF Bypass Server (Tier 2) via `--backend server`
- Crawls internal links, extracts emails, saves to JSON
- Supports `--proxy`, `--quick` (single page), `--depth N`
```bash
# Quick scan with curl_cffi
PYTHONPATH= python email_scraper_cf.py https://target.com --quick
# Full crawl with CF bypass server
PYTHONPATH= python email_scraper_cf.py https://target.com --backend server
# With residential proxy
PYTHONPATH= python email_scraper_cf.py https://target.com --proxy socks5://user:pass@host:port
```
## Decision flowchart
```
Is the site behind Cloudflare?
├── No → use requests / httpx directly
└── Yes → try curl_cffi (impersonate="chrome124")
├── Got 200 with content → done
└── Got 403 / "Checking your browser" / challenge page
└── Start CF Bypass Server → use /html or mirror mode
```
## Pitfalls
1. **First CF bypass server start downloads 535 MB** — plan ahead, start it before the scraping session
2. **Hermes PYTHONPATH locks playwright** — always `PYTHONPATH= python` when running the server or scraper
3. **curl_cffi impersonate versions** — `chrome124` is current; if sites start detecting it, try `chrome120`, `chrome110`, `safari17_0`
4. **CloakBrowser may trigger antivirus** — it's a modified Chromium binary; whitelist the directory
5. **Cookie cache is per-worker** — if using `--workers N`, each worker has its own cache; cookies are regenerated per worker
6. **Server uses significant RAM** — ~500 MB per worker; use `--workers 1` for scraping
## Tier 3: remote stealth render (firecrawl) — для SPA+Turnstile и когда локальный IP режет ассеты
Если локальные браузеры показывают белый экран (SPA-бандл висит в pending / ERR_CONNECTION_RESET), а curl и firecrawl качают тот же ассет с 200 — проблема в выходном IP, не в сайте. Работай через `firecrawl_scrape`/`firecrawl_interact` со stealth-прокси. Детали лимитов interact (60s MCP-таймаут, сессия живёт ~1-2 мин, лимит 2 джобов, паттерн Turnstile-регистрации) — `references/firecrawl-interact-turnstile-reg.md`.
## Tier 2.5: TRAWL — self-hosted FlareSolverr-killer (Bun + Camoufox + Redis + MCP)
**Repo**: https://github.com/germondai/trawl (AGPL-3.0, 979 stars, v1.8.0 08.10.2026 — активная разработка). Docs: https://docs.trawl.germondai.com
Когда: нужен ДОЛГОЖИВУЩЙ сервер обхода (не разовый скрипт) — парсинг под нагрузкой, *arr-стек (Prowlarr/Jackett/Sonarr), интеграция с AI-агентами через MCP. Многопрофильный: Cloudflare Turnstile/Interstitial, Akamai Bot Manager, Imperva/Incapsula, GeeTest Slide, Friendly Captcha v1/v2, ALTCHA, reCAPTCHA v2 (бесплатный audio через локальный Whisper), CAP proof-of-work. Всё локально, 2Captcha — опциональный fallback.
4-уровневая эскалация: Tier 0 plain HTTP → Tier 1 cached browser session (Redis) → Tier 2 fresh solve в Camoufox → Tier 3/4 (residential) proxy.
Деплой: `git clone https://github.com/germondai/trawl && cd trawl && cp .env.example .env && docker compose up -d`. API :8191 (`/health`, `/scrape`, FlareSolverr-compat `/v1`), MITM-прокси :8192 (MITM_ENABLED=true), MCP `/mcp` (MCP_ENABLED=true, Streamable HTTP: markdown/JSON-extract/screenshots/diagnostics). Дашборд :8191/dashboard. Первый старт 15-30с (browser pool warmup).
Детали и curl-примеры: `references/trawl-flaresolverr-replacement.md`.
## Related skills
- `anti-detection-browser` — browser automation for signup/registration flows (DrissionPage, nodriver)
- `bpproxy` — residential proxy generation for IP rotation
- `paywall-bypass` — bypassing paywalls on news sites

View File

@@ -0,0 +1,27 @@
# firecrawl_interact для Turnstile-регистраций + локальный «белый экран» SPA (2026-09-10, RainProxy)
## Симптом: SPA белый экран локально, но грузится через скрапер
`dashboard.rainproxy.io` в Playwright MCP, Chrome DevTools MCP и даже в реальном Chrome (pid 32312) — пустая страница. В DevTools network: `/assets/index.*.js` висит в **pending** / `ERR_CONNECTION_RESET`, при этом:
- `curl` качает тот же бандл: HTTP 200, 903KB;
- `firecrawl_scrape` с `waitFor` рендерит страницу полностью (видно форму логина).
Вывод: режет не сайт, а текущий выходной IP/путь. Диагноз за 2 шага:
1. `curl -o /dev/null -w "%{http_code} %{size_download}" <asset-url>` — если 200 и размер полный, файл жив;
2. `firecrawl_scrape(url, formats=[markdown], waitFor=8000)` — если контент есть, проблема в локальном IP, работать через stealth-скрапер.
## firecrawl_interact — жёсткие операционные лимиты (проверено вживую)
- **MCP-вызов умирает на 60s** независимо от `timeout=300` в аргументах. Сценарий «fill + поллить Turnstile 25s + click + wait» НЕ влезает → TimeoutError. Планировать фазы ≤45s чистого действия.
- **Сессия по scrapeId живёт ~1-2 мин.** Повторный вызов `interact(scrapeId=...)` позже → «Job not found». Двухфазный план ненадёжен — предпочитать ОДИН атомарный промпт (fill + checkbox + poll + click).
- **Лимит 2 параллельных джоба.** Зависшие сессии держат слоты; `interact_stop` по истёкшему scrapeId → 404. Освобождение только ожиданием ~2-3 мин.
- После 3-4 таймаутов MCP-сервер уходит в «unreachable, auto-retry in ~40s» — не спамить ретраями, спать и менять тактику.
## Turnstile-регистрация: что показал живой прогон
Заполненная форма + чекбокс terms + мгновенный клик Register (без ожидания Turnstile) → сервер возвращает валидацию:
- «Please verify you are not a robot» — Turnstile обязателен, клик до Success! бесполезен;
- «Please enter a valid email» на gmail **`+`-алиас** (`user+tag@gmail.com`). Dot-алиас (`user.tag@gmail.com`) — рабочая замена для мультиаккаунтинга.
Правильный атомарный промпт для interact (укладывается в 60s):
«Fill fields X; check terms; poll every 3s up to 25s until Turnstile shows Success!; click Register; report snapshot immediately.»
## Связь с tier-подходом этого скилла
Firecrawl stealth-прокси работает как Tier 3 (удалённый рендер), когда Tier 1 (curl_cffi) не适用 — SPA+Turnstile, и локальный IP режет ассеты. Для регистрации с обязательным Turnstile автоматизация без решения капчи не проходит — тот же вывод, что для proxyscrape (см. proxy-free-trial skill).

View File

@@ -0,0 +1,110 @@
# TRAWL — self-hosted FlareSolverr/Byparr replacement
Verified 13.10.2026: repo https://github.com/germondai/trawl (200), site https://trawl.germondai.com (200), docs https://docs.trawl.germondai.com (200). 979 stars, 59 forks, AGPL-3.0, v1.8.0 (08.10.2026), 582 commits, active dev.
## Что это
Self-hosted scraping engine. Заменяет мёртвый FlareSolverr и Byparr. Стек: Bun + Elysia (API), Redis 8.8 (session cache), Camoufox Firefox (browser automation, fingerprint-patched на C++/Juggler уровне), Nuxt 4 (UI), VitePress (docs). Monorepo: apps/ + packages/.
## Пробиваемые защиты (всё локально, без платных solver-API)
- Cloudflare: Turnstile, Interstitial/JS challenge
- Akamai Bot Manager
- Imperva / Incapsula
- GeeTest Slide
- Friendly Captcha v1/v2
- ALTCHA
- CAP proof-of-work
- reCAPTCHA v2 — бесплатный audio через локальный Whisper (STT_URL env)
- hCaptcha checkbox/audio where available
- Опциональный fallback: 2Captcha (reCAPTCHA v2/Enterprise, standalone Turnstile)
## 4-уровневая эскалация (tier pipeline)
1. Tier 0: plain HTTP fetch (мгновенно)
2. Tier 1: cached browser session из Redis (переиспользует решённые cookies + browser identity)
3. Tier 2: fresh challenge solve в Camoufox
4. Tier 3/4: (residential) proxy escalation — PROXY_LIST_FILE / RESIDENTIAL_PROXY_URL
## Деплой
```bash
git clone https://github.com/germondai/trawl
cd trawl
cp .env.example .env
docker compose up -d
curl http://localhost:8191/health
```
Первый старт 15-30с (browser pool warmup). Есть docker-compose.minimal.yml и docker-compose.prod.yml. One-click в каталогах TrueNAS (apps.truenas.com/catalog/trawl_community) и Unraid (ca.unraid.net/apps/trawl-1o4q23p06utr4h).
## API
FlareSolverr-compatible (drop-in для Prowlarr/Jackett/Sonarr/*arr):
```bash
curl -X POST http://localhost:8191/v1 \
-H 'Content-Type: application/json' \
-d '{"cmd":"request.get","url":"https://nowsecure.nl","maxTimeout":60000}'
```
Native API (богатая мета: tier, timings, sessionCached, полный список cookies):
```bash
curl -X POST http://localhost:8191/scrape \
-H 'Content-Type: application/json' \
-d '{"url":"https://nowsecure.nl","maxTimeout":60000}'
```
В Prowlarr: FlareSolverr URL = http://localhost:8191 (или http://trawl:8191 в compose-сети).
## MCP для AI-агентов
MCP_ENABLED=true → Streamable HTTP MCP-сервер на /mcp. Инструменты: чтение страниц как Markdown/text, scrape HTML, extract JSON records, screenshots (viewport/full-page/element), browser diagnostics. Грузит только известные публичные URL — web search НЕ даёт.
## Isolated browser sessions
Сохраняют login cookies и localStorage между native API / MCP / FlareSolverr запросами, capacity limits + auto idle expiry. Session API: docs.trawl.germondai.com/api-reference/browser-sessions
## MITM challenge-bypass proxy
Для сайтов, где CF clearance привязан к полному connection fingerprint (cookie не переносится — Prowlarr re-fetch своим клиентом ловит re-challenge):
```env
MITM_ENABLED=true
MITM_PORT=8192
MITM_CA_DIR=/data/proxy-ca # персист CA (volume)
MITM_MAX_TIER=4 # cap эскалации (3 = без residential)
MITM_ALWAYS_SCRAPE=false
MITM_HOST=0.0.0.0 # 127.0.0.1 для loopback-only
```
CA: `curl http://<host>:8191/proxy-ca.crt` → в trust store клиента. Prowlarr: Settings → Indexer Proxies → HTTP, порт 8192. Обычный трафик идёт direct; HTML/JSON/text буферизуются для challenge detection; видео/бинари стримятся; Range/206 end-to-end; WebSocket direct relay. ВНИМАНИЕ: MITM может impersonate любой хост — только private interface.
## Ключевые env
| Var | Default | Назначение |
|-----|---------|-----------|
| PORT | 8191 | API |
| STT_URL | — | локальный Whisper для reCAPTCHA audio |
| PROXY_LIST_FILE | — | Tier 3 proxy URLs (по строке) |
| RESIDENTIAL_PROXY_URL | — | включает Tier 4 |
| MCP_ENABLED | false | MCP-сервер |
| MITM_* | см. выше | forward proxy |
Полная таблица — README apps/docs/getting-started/configuration.md. При апгрейде со старых версий — migration guide (переименования env, Redis opt-in).
## Ключевые файлы репы
- apps/docs/integrations/mcp.md — MCP-интеграция
- apps/docs/proxy/overview.md — прокси-маршрутизация, CA, примеры клиентов
- apps/docs/deployment/configuration-migration.md — миграция env
- .env.example — полный список переменных
## Отношение к нашему стеку
- Camoufox у нас уже используется (BrowserMCP, SearchMCP, abliteration farm, conol) — знакомый runtime, те же pitfall'ы (geoip, launch timeout, SWGL crash — см. memory Camoufox pitfalls)
- Конкурент Tier 2 CloudflareBypassForScraping (sarperavci): TRAWL быстрее под нагрузкой (Redis session reuse), мульти-WAF, MCP из коробки, но требует Docker + Redis (тяжелее)
- Для *arr и постоянного парсинга — TRAWL; для разового скрипта — curl_cffi/CloakBrowser по-прежнему легче
- Бенчмарки авторов: trawl.germondai.com/#compare (same-machine, быстрее FlareSolverr и Byparr; результаты зависят от сайта/сессии)
- Спонсоры README: Bright Data, NodeMaven (промо TRAWL35/TRAWL40), Thordata (TRAWL10) — жилые прокси для Tier 4, если понадобятся

View File

@@ -0,0 +1,172 @@
#!/usr/bin/env python3
"""
Email scraper with CF bypass — two backends:
1. curl_cffi (lightweight, no browser, works now) ← DEFAULT
2. CF Bypass Server (full browser, for JS-challenge sites)
Usage:
python email_scraper_cf.py https://target.com
python email_scraper_cf.py https://target.com --backend server
python email_scraper_cf.py https://target.com --proxy socks5://user:pass@host:port
"""
import re
import sys
import time
import json
from urllib.parse import urljoin, urlparse
from typing import Optional
# ── Backend 1: curl_cffi (lightweight, TLS fingerprint impersonation) ──
try:
from curl_cffi import requests as cf_requests
HAS_CURL_CFFI = True
except ImportError:
HAS_CURL_CFFI = False
# ── Backend 2: CF Bypass Server (full browser) ──
import requests as std_requests
CF_BYPASS_URL = "http://localhost:8000"
# ── Config ──────────────────────────────────────────────────
MAX_PAGES = 50
REQUEST_TIMEOUT = 30
EMAIL_RE = re.compile(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}')
LINK_RE = re.compile(r'href=["\']([^"\']+)["\']')
# ────────────────────────────────────────────────────────────
def fetch_curl_cffi(url: str, proxy: Optional[str] = None) -> str:
"""Fetch using curl_cffi with Chrome 124 TLS fingerprint impersonation."""
if not HAS_CURL_CFFI:
raise RuntimeError("curl_cffi not installed. Run: pip install curl_cffi")
proxies = {"http": proxy, "https": proxy} if proxy else None
resp = cf_requests.get(
url,
impersonate="chrome124",
proxies=proxies,
timeout=REQUEST_TIMEOUT,
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/[REDACTED-IP] Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
}
)
return resp.text
def fetch_cf_server(url: str, proxy: Optional[str] = None) -> str:
"""Fetch through local CF Bypass Server (full browser JS challenge solve)."""
headers = {"x-hostname": urlparse(url).netloc}
if proxy:
headers["x-proxy"] = proxy
resp = std_requests.get(
f"{CF_BYPASS_URL}/html",
params={"url": url},
headers=headers,
timeout=REQUEST_TIMEOUT + 30, # browser solve takes longer
)
resp.raise_for_status()
return resp.text
def extract_emails(html: str) -> set[str]:
return set(EMAIL_RE.findall(html))
def extract_links(html: str, base_url: str) -> list[str]:
base = f"{urlparse(base_url).scheme}://{urlparse(base_url).netloc}"
links = []
for href in LINK_RE.findall(html):
full = urljoin(base_url, href)
if full.startswith(base) and not full.endswith(
(".jpg", ".png", ".pdf", ".zip", ".css", ".js", ".ico", ".svg", ".woff", ".woff2")
):
links.append(full)
return links
def crawl(start_url: str, proxy: Optional[str] = None, backend: str = "curl_cffi") -> dict[str, set[str]]:
fetch = fetch_curl_cffi if backend == "curl_cffi" else fetch_cf_server
seen: set[str] = set()
queue: list[str] = [start_url]
results: dict[str, set[str]] = {}
while queue and len(seen) < MAX_PAGES:
url = queue.pop(0)
if url in seen:
continue
seen.add(url)
try:
print(f"[{len(seen)}/{MAX_PAGES}] {url}")
html = fetch(url, proxy)
except Exception as e:
print(f" ⨯ {type(e).__name__}: {e}")
continue
emails = extract_emails(html)
if emails:
results[url] = emails
for e in emails:
print(f" ✉ {e}")
for link in extract_links(html, url):
if link not in seen:
queue.append(link)
time.sleep(0.3)
return results
def quick_scan(url: str, proxy: Optional[str] = None, backend: str = "curl_cffi") -> set[str]:
fetch = fetch_curl_cffi if backend == "curl_cffi" else fetch_cf_server
html = fetch(url, proxy)
return extract_emails(html)
# ── CLI ─────────────────────────────────────────────────────
if __name__ == "__main__":
if len(sys.argv) < 2:
print(__doc__)
sys.exit(1)
target = sys.argv[1]
backend = "curl_cffi"
proxy = None
quick = False
i = 2
while i < len(sys.argv):
if sys.argv[i] == "--backend" and i + 1 < len(sys.argv):
backend = sys.argv[i + 1]; i += 1
elif sys.argv[i] == "--proxy" and i + 1 < len(sys.argv):
proxy = sys.argv[i + 1]; i += 1
elif sys.argv[i] == "--quick":
quick = True
i += 1
if backend == "curl_cffi" and not HAS_CURL_CFFI:
print("curl_cffi not installed. Install: pip install curl_cffi")
print("Falling back to 'server' backend. Make sure CF Bypass Server is running on port 8000.")
backend = "server"
if quick:
emails = quick_scan(target, proxy, backend)
print(f"\n{len(emails)} emails on {target}:")
for e in sorted(emails):
print(f" {e}")
else:
results = crawl(target, proxy, backend)
total = sum(len(v) for v in results.values())
print(f"\n✓ {total} emails across {len(results)} pages")
out = {url: sorted(emails) for url, emails in results.items()}
with open("emails_output.json", "w", encoding="utf-8") as f:
json.dump(out, f, indent=2, ensure_ascii=False)
print(f"✓ Saved to emails_output.json")