feat: Robotex landing describes architecture v2

- how it works: async POST /v2/tasks + polling, window held between tasks,
  /v1/solve stays synchronous; example uses an http proxy and native Linux UA
- new "Architecture" section (api, RabbitMQ, worker, Redis) via the optional
  engine block; base engine styles moved into landing.css
- features: window between tasks, inner_text; limits: open window takes a slot

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
protokeyandClaude Opus 5.5 committed 2026-10-13 21:13:35 +04:00
1 parent 672467a699
commit d0c0b485c6
3 files changed
+116 -42

No files matched your search

+48 -21
View File
@@ -14,6 +14,7 @@ sitemap:
nav:
- { label: "Возможности", href: "#features" }
- { label: "Как работает", href: "#how" }
- { label: "Архитектура", href: "#engine" }
- { label: "Сообщество", href: "#community" }
cta:
@@ -33,28 +34,30 @@ features:
title: "Возможности"
items:
- title: "Сценарии"
text: "Не просто открыть страницу. Заполнить форму, кликнуть, навести мышь, дождаться элемента, забрать кусок HTML."
text: "Не просто открыть страницу. Заполнить форму, кликнуть, навести мышь, дождаться элемента, забрать кусок HTML или текст."
- title: "Анти-бот страницы"
text: "Сам находит проверку Cloudflare до и во время сценария и проходит ее. Если она переросла в капчу с картинками, отправляет в сервис распознавания."
- title: "Капча"
text: "Шаг `captcha` в сценарии решает hCaptcha и другие капчи через 2captcha до отправки формы."
- title: "Профили"
text: "Куки, local storage и отпечаток браузера живут в одном профиле. Локаль и часовой пояс подбираются под гео прокси. Для сайта это все тот же пользователь."
- title: "Настоящий Chrome"
text: "Chrome под управлением Patchright, без утечек CDP, по которым анти-боты узнают автоматизацию."
- title: "Окно между задачами"
text: "Браузер может подождать следующего шага до двух часов. Следующая задача выполнится в том же окне, без перезапуска Chrome и повторной проверки, прямо на открытой странице."
- title: "Любой язык"
text: "Это сервис, а не библиотека. Боту нужен только HTTP клиент, на чем он написан, неважно."
how:
title: "Как это работает"
steps:
- "Бот отправляет в `POST /v1/solve` адрес, сценарий действий и свой прокси."
- "Robotex открывает страницу, проходит проверки и выполняет сценарий. Профиль браузера сохраняется и возвращается в куке `session_id`."
- "Бот получает куки и User-Agent и дальше ходит по сайту сам, **через тот же прокси**. Понадобится браузер снова, передаст `session_id` и продолжит в том же профиле."
- "Бот отправляет в `POST /v2/tasks` адрес, сценарий действий и свой прокси. Задача встает в очередь, в ответ приходит ссылка на результат и кука `session_id`."
- "Свободный воркер открывает страницу в Chrome, проходит проверки и выполняет сценарий. Бот опрашивает ссылку, пока задача не станет `done`."
- "Бот получает куки и User-Agent и дальше ходит по сайту сам, **с тем же UA и через тот же прокси**."
- "Понадобится браузер снова, передаст `session_id`. Если просил подержать окно (`browser_idle_timeout`), задача выполнится в нем, можно даже без `url`. Если нет, Chrome откроется с тем же профилем."
- "Нужен ответ сразу, без опроса: `POST /v1/solve` работает как раньше, синхронно."
code:
- caption: "Запрос"
- caption: "Задача"
body: |
POST https://app.robotex.sokolab.xyz/v1/solve
POST https://app.robotex.sokolab.xyz/v2/tasks
{
"url": "https://example.com/login",
@@ -64,28 +67,52 @@ how:
{"type": "click", "selector": "#submit"},
{"type": "wait_for", "selector": ".dashboard", "timeout": 30}
],
"proxy": "socks5://user:pass@host:port"
"proxy": "http://user:pass@host:port",
"browser_idle_timeout": 10
}
- caption: "Ответ"
→ 202 {"task_id": "0b9c…", "status": "queued", "url": "/v2/tasks/0b9c…"}
- caption: "Результат: GET /v2/tasks/0b9c…"
body: |
{
"status": "ok",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
"cookies": [
{"name": "sessionid", "value": "...", "domain": ".example.com"}
],
"actions": [
{"type": "fill", "ok": true},
{"type": "fill", "ok": true},
{"type": "click", "ok": true},
{"type": "wait_for", "ok": true}
]
"task_id": "0b9c…",
"status": "done",
"result": {
"status": "ok",
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) ... Chrome/155.0.0.0 ...",
"cookies": [
{"name": "sessionid", "value": "...", "domain": ".example.com"}
],
"actions": [
{"type": "fill", "ok": true},
{"type": "fill", "ok": true},
{"type": "click", "ok": true},
{"type": "wait_for", "ok": true}
]
}
}
engine:
kicker: "Под капотом"
title: "Архитектура v2"
lead: "Раньше браузер жил прямо в API, и когда слоты кончались, запрос получал отказ. Теперь API только принимает задачи и отдает результаты, а Chrome работает в отдельных воркерах за очередью."
items:
- "**api** на FastAPI без браузера: ставит задачи, отдает статус и результат"
- "**RabbitMQ**: задачи ждут свободного слота в очереди, а не получают `503`"
- "**worker** на dramatiq: настоящий Chrome под Patchright и Xvfb, без утечек CDP, несколько окон на воркер"
- "**Redis**: статусы и результаты задач хранятся сутки, прокси и ключ 2captcha туда не попадают"
- "Задачи сессии с открытым окном идут в личную очередь того воркера, у которого это окно"
- "`/v1/solve` работает поверх той же очереди, старые клиенты ничего не меняют"
callout:
title: "Браузер больше не одноразовый"
text: "Окно можно держать открытым от 0 до 120 минут простоя и вести в нем сценарий по шагам: залогиниться, отдать управление боту, вернуться и продолжить на той же странице. Закрыть окно раньше можно через `DELETE /v2/sessions/current`."
limits:
title: "Честно о текущем состоянии"
items:
- "**Это ранний MVP.** Доступ открыт без регистрации и ключей, но API может меняться."
- "Открытое окно занимает слот браузера. Держите его не дольше, чем нужно."
- "Пока все воркеры работают на одном сервере."
- "**Бесплатно.** Платить нужно только за свои прокси и, если нужна, капчу в 2captcha."
- "Прокси решает многое: на грязном IP не поможет никакой отпечаток."
- "Turnstile проходит не на каждом сайте, над стабильностью работаю."