Капча, которую рисуют: drop‑in альтернатива reCAPTCHA на динамике жеста

от автора

Почему мы классифицируем движение руки, а не картинки со светофорами — и как встроить это в форму двумя строками

Картиночные капчи в 2026-м решаются моделями компьютерного зрения за миллисекунды, а каждый ваш клик по «выберите автобусы» бесплатно размечает чужой датасет. Плюс две свежие проблемы: Google в начале 2025 срезал бесплатный лимит reCAPTCHA с 1 000 000 до 10 000 проверок в месяц, а с апреля 2026 ужесточил модель ответственности за данные по GDPR. Из России reCAPTCHA к тому же нестабильна.

В сети существует общая проблема — как доказать, что ты человек, не сдавая паспорт, лицо и номер телефона. Предлагаемое решение: drop‑in капча, которую посетитель не кликает, а рисует. Ниже — архитектура, ML‑часть, приватность и код интеграции. Проект открытый. Визуальное описание процесса ниже

Идея: классифицировать моторику, а не форму

Пользователь рисует произвольный жест ~10 секунд. Мы смотрим не на то, ЧТО нарисовано, а на то, КАК: разброс скорости, паузы, микрокоррекции, ритм, остановки движения руки. Боты двигаются слишком гладко; человек нерегулярен — и эта нерегулярность и есть доказательство. Это та часть, которую боту пока дорого подделать убедительно.

Архитектура: почему iframe с нашего origin

Главная инженерная тонкость встраивания на чужой сайт — cross‑origin. Если бы виджет стучался на наш API напрямую со страницы клиента, ловил бы CORS/Origin‑локи и антибот‑фильтры.

Решение следующее: виджет — это <iframe>, который грузится с нашего домена, а не со страницы клиента. Внутри рамки все запросы идут к нашему же серверу, поэтому никаких cross‑origin проблем нет.

Чтобы понять, чей это сайт, у каждого клиента два ключа (как у reCAPTCHA):

  • публичный (pk_live_…) — вставляется в HTML, привязан к списку разрешённых доменов клиента. С чужого домена он бесполезен.

  • секретный (sk_live_…) — только на сервере клиента; им подтверждается токен.

Свой домен виджет узнаёт от родительской страницы и перепроверяет на сервере по списку разрешённых — подделать нельзя.

Блок-схема работы системы верификации по движению руки

Блок‑схема работы системы верификации по движению руки

ML: локальный GBM + LLM только для серой зоны

  • Из жеста считаются 8 признаков (velocity variance, pause entropy, rhythm irregularity, correction count и так далее).

  • Локальная градиентно‑бустинговая модель решает уверенные случаи за миллисекунды.

  • Языковая модель подключается только в серой зоне — где GBM не уверен.

  • Fail‑closed: если классификатор недоступен, endpoint отвечает 503, а не «человек: да». Лучше отказать, чем пропустить бота при сбое.

Приватность

Координаты жеста не покидают браузер — на сервер уходит только производная статистика. Никаких картиночных наборов, трекинг‑кук и хранимых биометрических шаблонов. Токен не несёт идентичности. Для GDPR это означает отсутствие передачи данных Google и, для самой проверки, отсутствие требования cookie‑баннера.

Интеграция: две строки + одна серверная проверка

Клиент (в форму, которую защищаем):

<script src="https://homosapience.org/embed/v2/aptogon.js"></script><div data-aptogon-captcha data-aptogon-key="pk_live_..."></div>

<div data-aptogon-captcha data-aptogon-key="pk_live_..."></div>

На успехе загрузчик добавляет в форму скрытое поле aptogon-response. Сервер клиента проверяет токен, как у reCAPTCHA:

curl -s https://homosapience.org/api/captcha/siteverify \  -H "Authorization: Bearer sk_live_..." \  -H "Content-Type: application/json" \  -d '{"token": "<aptogon-response из формы>"}'# → {"success": true, "human": true, "band": "...", "hostname": "https://ваш-сайт"}
-H "Authorization: Bearer sk_live_..." \-H "Content-Type: application/json" \-d '{"token": "<aptogon-response из формы>"}'# → {"success": true, "human": true, "band": "...", "hostname": "https://ваш-сайт"}

Токен одноразовый (повтор — 409), живёт 120 секунд. Секретный ключ — только на сервере.

Честные ограничения

Предлагаемое решение повышает планку, а не делает систему непробиваемой. Мотивированный противник со временем сможет имитировать динамику — как и для любого программного proof‑of‑human. Виджет сам по себе не останавливает распределённые флуды через резидентные прокси. И у «рисования» есть свои ограничения по доступности — встроена толерантность к моторным нарушениям, но это область, где можно проводить исследования и накапливать обратную связь для коррекции алгоритма.

RU‑контекст

В российском сегменте интернета наиболее популярна — Yandex SmartCaptcha (локализация данных, привязка к Yandex Cloud). Наша ниша — те, кому нужна приватность и self‑serve, а reCAPTCHA не подходит по доступности/GDPR.

Итог

Открытый код (AGPL-3.0), бесплатный тариф 1000 проверок/мес. (на стадии тестирования возможно больше). Живое демо: https://homosapience.org/embed/captcha‑demo.html. Документация: https://homosapience.org/developers. Исходники и примеры интеграции (HTML/React/ Node/Python/PHP): https://github.com/tulubyev/aptogon‑captcha.

Буду рад разбору в комментариях — особенно кейсам, где классификатор ошибается, и мнению, действительно ли «нарисовать» ощущается лучше невидимой проверки.

ссылка на оригинал статьи https://habr.com/ru/articles/1072718/