- user_agent в запросе → 422 с подсказкой брать UA из ответа: UA, отличный от реального Chrome, расходится с userAgentData и движком, Cloudflare такой браузер не пропускает (замер: родной 3/3, Chrome 147 и Windows — 0) (#87) - профиль хранит только отпечаток (экран, DPR), UA не подменяется (#89) - docs/Usage.md: практики для клиентов API — тот же UA и прокси, что у браузера, сессии, cookies, ошибки и повторы, таймауты, пример на httpx - README, docs/API.md, docs/Introduction.md; тесты под новый контракт Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
11 KiB
API
Как встраивать API в свой клиент (UA, прокси, сессии, повторы) — Usage.md.
Основной эндпоинт: POST /v1/solve. Открывает страницу в Chrome (через прокси клиента, если он задан), при необходимости проходит
антибот (Cloudflare Turnstile, reCAPTCHA), выполняет список действий и возвращает cookies, результаты действий и,
по запросу, HTML и скриншот.
GET /health (и GET /) — {"status": "ok", "browser_slots": N, "free_slots": M}.
X-API-Keyпока не проверяется (#4).
Запрос
POST /v1/solve
Content-Type: application/json
X-API-Key: <key>
Cookie: session_id=<id> # необязательно, см. «Сессии»
{
"url": "https://freelancehunt.com/projects",
"proxy": "http://user:pass@host:port",
"captcha_type": "cloudflare",
"actions": [
{"type": "wait_for", "selector": "a[href*=\"/project/\"]", "timeout": 60}
],
"html": true,
"timeout": 120
}
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
url |
string | — | обязательно. Страница, которую открываем |
proxy |
string | null |
scheme://[user:pass@]host:port, схема http, https или socks5 (Chrome не поддерживает socks5 с логином/паролем). По exit-IP прокси выставляются locale и timezone браузера; без прокси — настройки браузера по умолчанию |
actions |
array | — | обязательно, может быть пустым. Действия, см. ниже |
captcha_type |
string | null |
провайдер антибота: cloudflare или recaptcha. Без него шаг антибота пропускается — для сайтов за Cloudflare обязательно |
captcha |
string | null |
ключ сервиса распознавания (2captcha), если антибот не проходится без решения капчи |
captcha_detect_locator |
string | null |
локатор, по которому определяется, что на странице антибот |
captcha_success_locator |
string | null |
локатор, по которому определяется, что антибот пройден |
html |
bool | false |
вернуть HTML страницы после выполнения действий |
screenshot |
bool | false |
вернуть скриншот видимой области (PNG, base64) после действий — в том числе при ошибке действия или антибота |
timeout |
int, с | 60 |
таймаут навигации |
cookies |
array | null |
cookies для установки до навигации, формат Playwright: {name, value, domain, path, expires, httpOnly, secure, sameSite} или {name, value, url}. Заменяют cookies профиля: перед установкой все cookies профиля удаляются ([] — просто очистить). Без поля cookies профиля сохраняются |
disable_resources |
bool | false |
не грузить картинки, шрифты, медиа |
blocked_domains |
array | null |
домены, запросы к которым блокируются |
retries |
int | 1 |
попыток навигации |
retry_delay |
float, с | 1.0 |
пауза между попытками |
wait |
int, мс | 0 |
пауза после загрузки страницы |
google_search |
bool | false |
выставить Referer как переход из поиска Google |
Действия
Выполняются по порядку после прохождения антибота. Если антибот не пройден, действия не выполняются
(code: challenge_failed). На первой ошибке действия выполнение останавливается.
Обязательные поля проверяются до запуска браузера: неизвестный type, нет selector/value, captcha без ключа
в запросе, неверный proxy — ответ 422 с описанием в detail (стандартный формат FastAPI).
type |
Поля | Что делает |
|---|---|---|
wait_for |
selector, timeout (1–7200 с, по умолчанию 30) |
ждёт появления элемента; при таймауте — ошибка действия |
click |
selector |
клик по элементу |
submit |
selector |
клик и ожидание навигации |
fill |
selector, value |
вставка значения в поле |
mouse_move |
selector |
наведение курсора на элемент; нет элемента — ошибка selector not found |
delay |
value (секунды строкой, 0–600) |
пауза |
inner_html |
selector |
возвращает HTML элемента в result; нет элемента — ошибка selector not found |
captcha |
selector, value (тип: cloudflare, recaptcha, hcaptcha) |
решить капчу внутри страницы через 2captcha, нужен captcha в запросе |
pass_challenge |
selector (локатор успеха, необязательно) |
повторно пройти антибот, например после перехода на другую страницу; если не пройден — ошибка действия |
Ответ
Формат один для всех случаев: status — "ok" или "err", при ошибке — code и error. Поля без значения не
возвращаются.
Успех (антибот пройден, действия выполнены), HTTP 200:
{
"status": "ok",
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) ... Chrome/155.0.0.0 Safari/537.36",
"cookies": [{"name": "cf_clearance", "value": "...", "domain": ".freelancehunt.com", "...": "..."}],
"actions": [
{"type": "wait_for", "ok": true, "duration_ms": 14}
],
"html": "<head>...</head><body>...</body>",
"duration_ms": 6405
}
| Поле | Описание |
|---|---|
status |
"ok" — антибот пройден и все действия выполнены, иначе "err" |
code |
при "err": причина, см. таблицу ниже |
error |
при "err": текст ошибки; для упавшего действия — <type>: <текст> |
user_agent |
родной UA браузера, с которым проходили антибот. Используйте его в своём HTTP-клиенте вместе с cf_clearance (см. Usage.md) |
cookies |
все cookies контекста |
actions |
по элементу на выполненное действие: type, ok, result (результат или текст ошибки), duration_ms |
html |
только при "html": true |
screenshot |
только при "screenshot": true: PNG в base64 |
duration_ms |
общее время обработки запроса |
code |
HTTP | Когда | Что ещё есть в ответе |
|---|---|---|---|
no_slots |
503 + Retry-After |
все браузеры заняты (BROWSER_SLOTS), запрос не ставится в очередь |
— |
request_failed |
200 |
ошибка до действий: навигация, прокси, неизвестный captcha_type |
actions: [] |
challenge_failed |
200 |
антибот не пройден за отведённое время, действия не выполнялись | cookies, html, screenshot |
action_failed |
200 |
упало действие, выполнение остановлено на нём | cookies, html, screenshot, actions до упавшего включительно |
Примеры:
{"status": "err", "code": "action_failed", "error": "inner_html: selector not found: #missing",
"actions": [{"type": "inner_html", "ok": false, "result": "selector not found: #missing", "duration_ms": 26}], "...": "..."}
{"status": "err", "code": "challenge_failed", "error": "cloudflare not passed: timeout (stage: checkbox)", "actions": [], "...": "..."}
{"status": "err", "code": "no_slots", "error": "No slots available"}
Сессии
Ответ ставит cookie session_id (UUID). Если передать её в следующем запросе, браузер откроется с тем же профилем
(extra/user_data_dir/<session_id>): cookies, localStorage и отпечаток сохраняются, повторно проходить Cloudflare
обычно не нужно. Без cookie или с некорректным значением (не UUID) запрос получает новый профиль.
Отпечаток профиля генерируется при первом запросе сессии и дальше не меняется (robotex_session.json в каталоге
профиля): размер экрана и devicePixelRatio десктопного Chrome на Linux из реального распределения (browserforge).
Применяется нативной эмуляцией Chrome, без JS-подмены (она ломала прохождение Cloudflare); DPR влияет и на хеш
canvas. Ограничение: canvas, WebGL и hardwareConcurrency у всех профилей одинаковые, поэтому примерно половина
профилей совпадает по отпечатку.
User-Agent и размер окна запросом не задаются — это родные значения браузера (почему — Usage.md).
Поле user_agent в запросе даёт 422.
Один профиль нельзя использовать в двух запросах одновременно: Chrome заблокирует каталог профиля.
Производительность
Каждый запрос запускает отдельный Chrome: около 0,6 ГБ памяти и до 3–4 ядер на пике при прохождении Cloudflare. Замеры и рекомендации по лимитам — в Deployment.md.