Для скрипта автоматизации reCAPTCHA Enterprise неотличима от v3: тот же виджет, тот же формат токена. Асимметрия начинается на сервере владельца сайта — там работает Assessment API, возвращающий не только балл, но и его причины с метками Account Defender.
Отсюда три следствия:
- проект в Google Cloud нужен оператору сайта, а не получателю токена;
- на клиенте меняются две вещи — имя скрипта и имя объекта JS;
- в запросе к сервису решения добавляется флаг
enterprise=1.
Как выглядит поток запроса: клиент отдельно, сервер отдельно
Из последовательности вызовов видно, что воспроизводится на клиенте.
Client-side:
1. Load reCAPTCHA Enterprise script
2. Call grecaptcha.enterprise.execute(SITE_KEY, {action: 'LOGIN'})
3. Receive token
4. Send token to your backend
Server-side:
1. Create assessment via Enterprise API
2. Receive detailed risk analysis
3. Make access decision based on score + reasons
4. Optionally annotate the assessment (report fraud/legitimate)
Шаги 1–4 выполняет браузер посетителя — их и воспроизводит сервис решения.
- для получения токена достаточно клиентской половины;
- всё, ради чего покупают Enterprise, — в серверной;
- «токен есть, доступа нет» живёт на стыке половин.
Что Enterprise добавляет к бесплатной reCAPTCHA v3
| Возможность | reCAPTCHA v3 (бесплатно) | reCAPTCHA Enterprise |
|---|---|---|
| Оценка | балл 0,0–1,0 | балл 0,0–1,0 + причины оценки |
| Анализ рисков | базовый | детальный (сигналы мошенничества, данные аккаунта) |
| Причины оценки | нет | конкретные причины балла |
| Account Defender | нет | да (жизненный цикл аккаунта) |
| Интеграция с WAF | нет | да (Cloudflare, Fastly, F5) |
| Express assessment | нет | да (только на стороне сервера, без JS) |
| Обнаружение утечки пароля | нет | да |
| Стоимость | бесплатно (1 000 000 оценок/мес) | $1 за 1000 оценок сверх 1 000 000 |
| Конечная точка API | google.com/recaptcha/api/siteverify | recaptchaenterprise.googleapis.com |
Работу клиента это не меняет: за оценки платит оператор сайта.
Клиентская часть: как Enterprise виден в разметке
Три отличия в JavaScript SDK
Отличий от v3 три:
- вместо
.../recaptcha/api.jsв URL стоит.../recaptcha/enterprise.js; - объект API —
grecaptcha.enterprise, а неgrecaptcha; execute()возвращает токен того же формата.
<script src="https://www.google.com/recaptcha/enterprise.js?render=SITE_KEY"></script>
<script>
grecaptcha.enterprise.ready(function() {
grecaptcha.enterprise.execute('SITE_KEY', { action: 'LOGIN' })
.then(function(token) {
// Send token to backend
fetch('/api/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: token })
});
});
});
</script>
Метка action сверяется на сервере — к ней вернёмся ниже.
Определение варианта по исходнику страницы
Определяйте вариант заранее: ошибка здесь — частая причина отказа.
import requests
import re
def detect_recaptcha_enterprise(url):
"""Detect if a page uses reCAPTCHA Enterprise."""
html = requests.get(url, timeout=10).text
indicators = {
"is_enterprise": False,
"is_standard": False,
"site_key": None,
"actions": [],
}
# Enterprise detection
if "recaptcha/enterprise.js" in html:
indicators["is_enterprise"] = True
match = re.search(r"render=([A-Za-z0-9_-]+)", html)
if match:
indicators["site_key"] = match.group(1)
# Standard v3 detection
elif "recaptcha/api.js?render=" in html:
indicators["is_standard"] = True
match = re.search(r"render=([A-Za-z0-9_-]+)", html)
if match:
indicators["site_key"] = match.group(1)
# Extract action names
actions = re.findall(r"action:\s*['\"](\w+)['\"]", html)
indicators["actions"] = list(set(actions))
return indicators
print(detect_recaptcha_enterprise("https://staging.example.com/qa-login"))
Она же вытаскивает sitekey и значения action.
Серверная часть: что возвращает Assessment API
Создание оценки в Google Cloud
from google.cloud import recaptchaenterprise_v1
from google.cloud.recaptchaenterprise_v1 import Assessment
def create_assessment(project_id, site_key, token, action):
"""Create a reCAPTCHA Enterprise assessment."""
client = recaptchaenterprise_v1.RecaptchaEnterpriseServiceClient()
event = recaptchaenterprise_v1.Event()
event.site_key = site_key
event.token = token
event.expected_action = action
assessment = recaptchaenterprise_v1.Assessment()
assessment.event = event
request = recaptchaenterprise_v1.CreateAssessmentRequest()
request.assessment = assessment
request.parent = f"projects/{project_id}"
response = client.create_assessment(request)
return response
Структура ответа
{
"name": "projects/123456/assessments/abcdef123",
"event": {
"token": "...",
"siteKey": "6Le...",
"expectedAction": "LOGIN",
"hashedAccountId": "abc123..."
},
"riskAnalysis": {
"score": 0.9,
"reasons": [
"AUTOMATION",
"TOO_MUCH_TRAFFIC"
],
"extendedVerdictReasons": [
"BROWSER_ERROR"
]
},
"tokenProperties": {
"valid": true,
"hostname": "example.com",
"action": "LOGIN",
"createTime": "2025-01-15T10:30:00Z",
"invalidReason": ""
},
"accountDefenderAssessment": {
"labels": ["PROFILE_MATCH"]
}
}
riskAnalysis.reasons и accountDefenderAssessment есть только в ответе Assessment API: в браузер они не попадают, и на чужом сайте причины балла не видны.
Блок tokenProperties полезен иначе: valid, hostname и action показывают, корректно ли собран запрос.
Причины оценки: почему балл занижен
Enterprise называет причину занижения. Третья колонка — порядок влияния, не коэффициент.
| Причина | Что означает | Влияние на балл |
|---|---|---|
AUTOMATION |
автоматизированный user-agent или браузер в headless-режиме | от -0,3 до -0,7 |
UNEXPECTED_ENVIRONMENT |
несоответствие окружения браузера или устройства | от -0,2 до -0,4 |
TOO_MUCH_TRAFFIC |
много запросов с этого IP или сессии | от -0,1 до -0,3 |
UNEXPECTED_USAGE_PATTERNS |
поведение расходится с человеческим | от -0,2 до -0,5 |
LOW_CONFIDENCE_SCORE |
данных для уверенной оценки мало | переменное |
SUSPECTED_CARDING |
признаки мошенничества с картами | от -0,3 до -0,6 |
SUSPECTED_CHARGEBACK |
риск возврата платежа | от -0,2 до -0,4 |
extendedVerdictReasons описывает не поведение, а технику запроса.
Extended verdict reasons
| Причина | Что означает |
|---|---|
BROWSER_ERROR |
ошибки JavaScript в SDK CAPTCHA |
SITE_MISMATCH |
токен выпущен для другого сайта |
FAILED_TWO_FACTOR |
недавний провал двухфакторной аутентификации |
Account Defender: оценка аккаунта, а не запроса
Account Defender смотрит на историю аккаунта, поэтому метки срабатывают и на безупречном запросе.
{
"accountDefenderAssessment": {
"labels": [
"PROFILE_MATCH",
"SUSPICIOUS_LOGIN_ACTIVITY",
"SUSPICIOUS_ACCOUNT_CREATION",
"RELATED_ACCOUNTS_NUMBER_HIGH"
]
}
}
| Метка | Значение |
|---|---|
PROFILE_MATCH |
поведение совпадает с профилем аккаунта |
SUSPICIOUS_LOGIN_ACTIVITY |
вход с нового устройства или региона |
SUSPICIOUS_ACCOUNT_CREATION |
регистрация выглядит автоматизированной |
RELATED_ACCOUNTS_NUMBER_HIGH |
много аккаунтов на одном устройстве |
Правило для QA-стендов: синтетические учётные записи под каждый прогон.
Интеграция с WAF: проверка до того, как запрос дойдёт до приложения
При подключении к WAF проверка появляется не на форме, а на промежуточном экране.
Cloudflare WAF
Request arrives at Cloudflare edge
↓
Cloudflare WAF rule evaluates request
↓
Rule triggers reCAPTCHA Enterprise challenge
↓
Client solves CAPTCHA → token returned
↓
Cloudflare validates token via Enterprise API
↓
If valid + score above threshold → request forwarded to origin
F5 BIG-IP
F5 iRule or policy evaluates request
↓
Triggers reCAPTCHA Enterprise challenge page
↓
Client solves → token validated server-side
↓
F5 forwards or blocks based on assessment score
Отсюда правило: pageurl — URL с виджетом, а не адрес формы.
Enterprise в автоматизации: один флаг вместо отдельного метода
Отдельного метода нет, запрос собирается как для v2/v3:
- метод
userrecaptcha; googlekeyиpageurlсо страницы;- флаг
enterprise: 1; - результат — опросом
res.php, полеg-recaptcha-response.
Python
import requests
import time
API_KEY = "YOUR_API_KEY"
# Enterprise is solved with the same method
# The solver handles the Enterprise variant automatically
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp",
"pageurl": "https://enterprise-site.com/login",
"enterprise": 1, # Flag for Enterprise variant
"json": 1,
})
task_id = submit.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}).json()
if result.get("status") == 1:
token = result["request"]
print(f"Enterprise token: {token[:50]}...")
break
Интервал 5 с и лимит попыток снимают бесконечное ожидание при обрыве.
Node.js
const axios = require("axios");
async function solveEnterprise(sitekey, pageurl) {
const API_KEY = "YOUR_API_KEY";
const { data: submit } = await axios.post(
"https://ocr.captchaai.com/in.php",
new URLSearchParams({
key: API_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageurl,
enterprise: 1,
json: 1,
})
);
const taskId = submit.request;
for (let i = 0; i < 60; i++) {
await new Promise(r => setTimeout(r, 5000));
const { data: result } = await axios.get(
"https://ocr.captchaai.com/res.php",
{ params: { key: API_KEY, action: "get", id: taskId, json: 1 } }
);
if (result.status === 1) return result.request;
}
throw new Error("Timeout");
}
Быстрая проверка версии перед отправкой
Дешевле классифицировать страницу заранее, чем разбирать отказы.
def identify_recaptcha_version(html):
"""Determine which reCAPTCHA version a page uses."""
if "recaptcha/enterprise.js" in html:
return "enterprise"
elif "recaptcha/api.js?render=" in html:
return "v3"
elif "g-recaptcha" in html and 'data-size="invisible"' in html:
return "v2_invisible"
elif "g-recaptcha" in html:
return "v2"
else:
return "none"
Типичный сценарий команд в Алматы, Минске или Тбилиси: на QA-стенде магазина вход закрыт reCAPTCHA Enterprise, и регрессионные прогоны падают до бизнес-логики. Тарификация CaptchaAI идёт по потокам, а не за решение, поэтому прогон из 400 проверок и из 40 стоят одинаково: BASIC ($15/мес, 5 потоков) закрывает небольшой набор тестов, STANDARD ($30/мес, 15 потоков) — параллельные сценарии.
Про 152-ФЗ «О персональных данных» помните отдельно: берите синтетические учётные данные.
Диагностика: пять типовых отказов
| Симптом | Вероятная причина | Что сделать |
|---|---|---|
| Токен отклонён Assessment API | для Enterprise-сайта ушёл обычный запрос | добавьте enterprise=1 |
| Балл стабильно 0,1 при валидном токене | не совпал action |
сверьте action с исходником страницы |
SITE_MISMATCH в причинах |
токен выпущен для другого домена | приведите pageurl к целевой странице |
AUTOMATION в причинах оценки |
сигналы автоматизации в окружении | как правило, обрабатывается на стороне CaptchaAI; при повторении — в поддержку |
| Токен валиден, но доступ закрыт | есть проверки помимо CAPTCHA | ищите другие уровни защиты (WAF, серверные правила) |
По покрытию: reCAPTCHA v2 и v3 с Enterprise-вариантами, Cloudflare Turnstile и Challenge, GeeTest v3, image/OCR, grid и BLS; CaptchaFox (beta), Friendly Captcha (beta), Lemin (beta) — в бете; hCaptcha и FunCaptcha не поддерживаются, GeeTest v4 — «скоро».
Часто задаваемые вопросы
Нужно ли менять код, если сайт перешёл с v3 на Enterprise?
Достаточно добавить enterprise: 1. Метод userrecaptcha, googlekey, pageurl, поле g-recaptcha-response и опрос res.php не меняются.
Почему причины оценки не видны в ответе сервиса решения?
Причины Assessment API отдаёт владельцу сайта, а не браузеру. Сервис воспроизводит клиентскую часть и возвращает токен; riskAnalysis.reasons видны лишь в проекте Google Cloud.
Что означает action и почему из-за него падает балл?
action — метка сценария (LOGIN, CHECKOUT) из grecaptcha.enterprise.execute(). Если сервер ждёт одно значение, а токен выпущен с другим, оценка занижается независимо от качества токена. Вычитывайте значение из исходника.
Что делать, если проверка появляется на экране WAF, а не на форме?
В pageurl передавайте адрес экрана с виджетом: промежуточная страница Cloudflare или F5 — отдельный URL.
Сколько потоков нужно для регулярных прогонов по Enterprise-страницам?
Считайте от параллелизма: один поток — одна задача. Пяти потоков в BASIC ($15/мес) хватает небольшому набору тестов, 50 потоков в ADVANCE ($90/мес) — параллельному CI.
Коротко
Assessment API — серверная надстройка над знакомой reCAPTCHA: анализ рисков, причины оценки, метки Account Defender, WAF. Для автоматизации меняется немногое: определить вариант по recaptcha/enterprise.js, передать корректный action, указать верный pageurl и добавить enterprise=1 в запрос к CaptchaAI.