- Dockerfile: python 3.12, Google Chrome (patchright), Xvfb, tini как PID 1 против зомби-процессов - docker-compose: volume для extra/, shm_size 2gb, порт через API_PORT - requirements: добавлены playwright и camoufox - docs: Deployment.md, README и доки актуализированы под Chrome Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4.9 KiB
Robotex
Browser automation API with built-in anti-bot stealth. Send a URL and a sequence of declarative actions — fill a field, click, wait for an element — and get back the rendered page, including sites behind Cloudflare-style JS challenges.
Status
Early MVP (v0), under active development. Single browser engine, no queue, no billing yet — see Roadmap.
Architecture
Client → Caddy (TLS) → FastAPI → API-key auth → semaphore acquire
│
▼
Chrome (Patchright) context
(run actions, collect result)
│
▼
release semaphore → response
- Engine: real Google Chrome (
channel="chrome") driven via Patchright (undetected Playwright fork), headful under Xvfb. Firefox is not supported yet. - API: FastAPI, single versioned endpoint (
POST /v1/solve). - Concurrency: bounded by an
asyncio.Semaphoreover browser contexts — no external job queue in v1. Simpler to run, hard ceiling on throughput per instance (see Roadmap for scaling out). - Auth: per-client API key (
X-API-Keyheader), checked against a SQLite table. (SQLAlchemy ORM) - Logging: every request's outcome (success/failure/duration) is persisted — this becomes the success-rate data used to evaluate the service and talk to clients about reliability.
- Proxies: not managed by the service in v1 — the client supplies their own proxy per request if they need one.
- Deployment: single Docker container behind a Caddy reverse proxy — see Docker and docs/Deployment.md.
- Canvas fingerprint по дизайну генерируется каждую сессию новый.
Project layout
src/
main.py # FastAPI app, POST /v1/solve
api/
actions.py # fill / click / wait_for execution
schemas.py # SolveRequest / Action models
geoip.py # proxy → locale / timezone
engine/
stealthy.py # AsyncStealthySession (Patchright + Chrome)
session.py # browser / context launch options
page_pool.py # page pool
antibot/ # anti-bot detection & bypass orchestrator (Cloudflare, reCAPTCHA)
captcha/ # captcha solvers (Turnstile, reCAPTCHA, hCaptcha)
tests/
wheels/ # whl библиотеки для оффлайн установки под Ubuntu Noble
Dockerfile
docker-compose.yml
.dockerignore
requirements.txt
env.example
API (draft)
POST /v1/solve
X-API-Key: <key>
{
"captcha": "token",
"url": "https://example.com/login",
"actions": [
{"type": "fill", "selector": "#email", "value": "user@example.com"},
{"type": "fill", "selector": "#password", "value": "..."},
{"type": "mouse_move", "selector": "#submit"},
{"type": "click", "selector": "#submit"},
{"type": "wait_for", "selector": ".dashboard", "timeout": 30}
],
"proxy": "socks5://user:pass@host:port",
"screen": "1280x920",
"user_agent": "Mozilla/5.0 (...) Chrome/...",
"timeout": 120
}
Response:
{
"ok": false,
"context": "000000",
"error": "action_error",
"html": "<html>...</html>",
"cookies": [
{
"name": "session",
"value": "..."
}
],
"actions_result": [
{
"type": "fill",
"ok": true
},
{
"type": "fill",
"ok": true
},
{
"type": "click",
"ok": true
},
{
"type": "wait_for",
"ok": false,
"error": "Element not located"
}
]
}
On failure, status is "error" and error carries a machine-readable reason (selector_not_found, timeout,
navigation_failed, ...).
Fill команда включает 3 действия
{"type": "mouse_move", "selector": "#email"},- навести мышку на элемент{"type": "click"},- клик в текущие координаты{"type": "typing", "value": "user@example.com"},- набор текста
Roadmap
Deliberately out of scope for v1:
- Job queue (Redis/RabbitMQ) + multiple worker VPS for horizontal scaling
- Real billing/usage plans beyond a flat API-key check
- Broader action vocabulary beyond fill/click/wait_for
- Second engine (Firefox, e.g. Camoufox) for targets where the Chrome fingerprint doesn't fit
Local development
python -m venv .venv
source .venv/bin/activate
make sync-offline
cd src && uvicorn main:app --reload
Docker
docker compose up -d --build
The API listens on http://localhost:8000. Browser profiles (extra/user_data_dir) and the GeoIP cache live in the
extra named volume, so sessions survive container restarts. Details (Xvfb, tini, /dev/shm) —
docs/Deployment.md.