Подключение капчи к сайту
Три шага: получить ключи, вставить виджет в форму, проверить токен на сервере.
1. Ключи
Подключите сайт в кабинете — укажите домены, на которых будет работать виджет. Вы получите sitekey (публичный, для страницы) и secret (только для сервера; показывается один раз).
Режимы проверки
| Режим | Что видит посетитель | Что делает сайт |
|---|---|---|
| Стандартный | Галочку (или ничего — в невидимом режиме); задание — только при подозрении: символы, слайдер, выбор картинок или поворот | Пропускает при success: true |
| Только оценка как reCAPTCHA v3 | Никаких заданий | Сам решает по score: например, ≥ 0.5 — SMS, модерация или отказ |
| Только proof-of-work | Галочка ставится сама за секунду, без кликов | Пропускает при success: true; телеметрия не собирается — подходит, когда важна приватность, но защищает только от массовых ботов |
Режим и набор заданий — в настройках сайта в кабинете или через API кабинета.
2. Виджет
Галочка «Я не робот» в форме:
<script src="https://captcha.mpdevelop.ru/widget.js" async defer></script>
<form method="post" action="/register">
<input name="email">
<div class="captcha-widget"
data-sitekey="ck_…"
data-action="registration"
data-callback="onCaptcha"></div>
<button>Зарегистрироваться</button>
</form>
| Атрибут | Назначение |
|---|---|
data-sitekey | Публичный ключ сайта (обязателен) |
data-action | Действие: login, registration… Попадает в токен, сервер может требовать совпадения. Латиница, цифры, _, / |
data-callback | Имя глобальной функции, вызывается с токеном |
data-expired-callback | Токен истёк (через 3 минуты) — галочка снята, нужно пройти снова |
data-error-callback | Ошибка проверки, аргумент — код ошибки |
data-theme | light или dark |
data-lang | ru или en; по умолчанию — язык страницы (<html lang>), затем браузера |
data-input-name | Имя скрытого поля токена, по умолчанию captcha-token |
Невидимый режим — без галочки, проверка при отправке формы:
form.addEventListener('submit', async (event) => {
event.preventDefault();
const token = await CaptchaWidget.execute({ sitekey: 'ck_…', action: 'login' });
form.elements['captcha-token'].value = token;
form.submit();
});
Задание поверх страницы появится только при высоком риске. Без клика у сервиса меньше сигналов, поэтому невидимый режим чаще показывает задание на уровнях защиты «Высокий» и выше.
API: CaptchaWidget.render(el, options) → id, execute(id | {sitekey, action}) → Promise<token>,
reset(id), getResponse(id).
3. Проверка на сервере
POST https://captcha.mpdevelop.ru/api/v1/verify, тело form-urlencoded или JSON:
| Поле | Назначение |
|---|---|
secret | Секретный ключ (или заголовок Authorization: Bearer …) |
token | Значение поля captcha-token из формы |
action | Необязательно: ожидаемое действие; при несовпадении — action-mismatch |
ip | Необязательно: IP посетителя; в ответе будет ip_match |
{"success": true, "score": 0.1, "action": "registration", "hostname": "example.com",
"challenge": false, "challenge_type": null, "challenge_ts": "2026-10-06T12:00:00+00:00", "ip_match": true}
{"success": false, "error": "invalid-or-used-token"}
Ошибки: missing-input, invalid-secret, invalid-token, invalid-or-used-token
(истёк или уже проверен), token-site-mismatch, action-mismatch, rate-limited.
Пример на PHP без зависимостей:
$response = file_get_contents('https://captcha.mpdevelop.ru/api/v1/verify', false, stream_context_create(['http' => [
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded',
'content' => http_build_query([
'secret' => getenv('CAPTCHA_SECRET'),
'token' => $_POST['captcha-token'] ?? '',
'action' => 'registration',
'ip' => $_SERVER['REMOTE_ADDR'],
]),
'timeout' => 3,
]]));
$ok = ($response !== false) && (json_decode($response, true)['success'] ?? false) === true;
Токен одноразовый и живёт 3 минуты. Проверяйте его до выполнения действия, а не после.
Готовый клиент — пакет sdk/php в репозитории сервиса.
mode — standard, score или pow (в режиме pow score = null).
challenge_type — image (символы), slider (пазл), grid (картинки), rotate (поворот), audio (аудио-задание для незрячих) или null
(прошёл без задания). Аудио проще для ботов с распознаванием речи — для особо чувствительных действий это можно учесть.
Готовые интеграции
- Symfony — бандл:
$builder->add('captcha', CaptchaType::class, ['action' => 'login']), атрибут#[CaptchaValid],{{ captcha_widget('login') }}. - Laravel —
@captcha('login')в Blade и правило'captcha-token' => 'required|captcha:login'. - 1С-Битрикс — модуль
captcha.client: регистрация, вход и веб-формы без правки кода.
Пакет startup/captcha-client (sdk/php) и модуль sdk/bitrix в репозитории сервиса — там же инструкции.
API кабинета
Сайтами и ключами можно управлять из скриптов и CI. Токен — в кабинете, раздел «API»; передаётся заголовком Authorization: Bearer cpt_….
| Запрос | Что делает |
|---|---|
GET /api/v1/sites | Список своих сайтов |
POST /api/v1/sites | Подключить сайт; ответ содержит secret — единственный раз |
GET · PATCH · DELETE /api/v1/sites/{id} | Посмотреть, изменить настройки, удалить |
POST /api/v1/sites/{id}/secret | Выпустить новый секрет (старый перестаёт работать сразу) |
GET /api/v1/sites/{id}/stats?days=30&period=7d | Дневная статистика и аналитика |
curl -X PATCH https://captcha.mpdevelop.ru/api/v1/sites/7 \
-H "Authorization: Bearer $CAPTCHA_API_TOKEN" -H "Content-Type: application/json" \
-d '{"security_level": "high", "action_limits": {"login": {"limit": 10, "window": 600}}}'
Поля сайта: name, hosts, security_level,
action_levels, action_limits, enabled, verification_mode, challenge_types. Ошибки проверки — 422 с разбором по полям.
Определение провайдера по IP: IP to ASN by DB-IP (CC BY 4.0).