Со стороны интеграции разница ровно одна: в запрос к CaptchaAI добавляется enterprise=1. Остальное совпадает — метод userrecaptcha, version=v3, формат ответа. Сложность не в решении, а в диагностике: обе редакции невидимы и различаются только по коду страницы. Поэтому большинство сбоев на v3 — это не «капча не решилась», а неверно определённая редакция или неправильно снятый action.
Что реально различается между версиями
Обе редакции считают поведенческий балл от 0,0 до 1,0 и отдают токен; решение о доступе принимает бэкенд сайта. Enterprise добавляет коды причин, настраиваемые пороги и биллинг через Google Cloud — то есть расширяет аналитику владельца сайта, а не меняет задачу решения.
Для автоматизации:
- Определение редакции обязательно — флаг наугад ломает проверку в обе стороны.
actionкритичен для обеих: при несовпадении балл падает, токен отклоняется.- Время решения от редакции не зависит.
Как отличить Enterprise v3 от обычной v3
Ориентир один — какой JS-файл подключает страница: enterprise.js означает Enterprise, api.js?render= — стандартную v3. Проверяйте при каждой загрузке, а не однократно при написании скрипта.
Python:
import requests
import re
def detect_v3_type(url):
resp = requests.get(url)
html = resp.text
# Check for enterprise.js
if "enterprise.js" in html:
version = "enterprise_v3"
execute_fn = "grecaptcha.enterprise.execute"
elif "recaptcha/api.js" in html and "render=" in html:
version = "standard_v3"
execute_fn = "grecaptcha.execute"
else:
return None
# Extract sitekey from render parameter
key_match = re.search(r'render[=:]\s*["\']?([A-Za-z0-9_-]{40})', html)
sitekey = key_match.group(1) if key_match else None
# Extract action parameter
action_match = re.search(r'action["\']?\s*[:=]\s*["\'](\w+)', html)
action = action_match.group(1) if action_match else "unknown"
return {
"version": version,
"sitekey": sitekey,
"action": action,
"execute_fn": execute_fn
}
info = detect_v3_type("https://staging.example.com/qa-login")
print(info)
Node.js:
const axios = require("axios");
async function detectV3Type(url) {
const { data: html } = await axios.get(url);
let version, executeFn;
if (html.includes("enterprise.js")) {
version = "enterprise_v3";
executeFn = "grecaptcha.enterprise.execute";
} else if (html.includes("recaptcha/api.js") && html.includes("render=")) {
version = "standard_v3";
executeFn = "grecaptcha.execute";
} else {
return null;
}
const keyMatch = html.match(/render[=:]\s*['"]?([A-Za-z0-9_-]{40})/);
const actionMatch = html.match(/action['"]?\s*[:=]\s*['"](\w+)/);
return {
version,
sitekey: keyMatch?.[1] || null,
action: actionMatch?.[1] || "unknown",
executeFn,
};
}
Консоль браузера:
// Paste in DevTools console
if (document.querySelector('script[src*="enterprise.js"]')) {
console.log("Enterprise v3");
console.log("Execute:", typeof grecaptcha?.enterprise?.execute);
} else if (document.querySelector('script[src*="api.js"][src*="render="]')) {
console.log("Standard v3");
console.log("Execute:", typeof grecaptcha?.execute);
}
Функция возвращает редакцию, sitekey и action — всё, что нужно для запроса.
Таблица различий
| Характеристика | reCAPTCHA v3 | reCAPTCHA v3 Enterprise |
|---|---|---|
| Работа без виджета, балл 0,0–1,0 | Да | Да |
| Параметр action | Обязателен | Обязателен |
| JS-файл | api.js?render=KEY |
enterprise.js?render=KEY |
| Функция вызова | grecaptcha.execute() |
grecaptcha.enterprise.execute() |
| Коды причин | Нет | Да (AUTOMATION, TOO_MUCH_TRAFFIC) |
| Свои пороги, утечки паролей, Account Defender | Нет | Да (через Cloud Console) |
| Конечная точка проверки | siteverify |
recaptchaenterprise.googleapis.com |
| Параметры CaptchaAI | version=v3 |
version=v3 + enterprise=1 |
| Типичное время решения | 10–20 с | 10–20 с |
Правая колонка — возможности владельца сайта. Клиенту API важны только две последние строки.
Решение через CaptchaAI
Схема одна: отправить задачу в in.php, сохранить ID, опрашивать res.php.
Стандартная v3
import requests
import time
# Submit
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"version": "v3",
"googlekey": sitekey,
"action": "login",
"pageurl": page_url
})
task_id = resp.text.split("|")[1]
# Poll
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY", "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
token = result.text.split("|")[1]
break
Enterprise v3
Отличие ровно в одной строке — "enterprise": 1:
import requests
import time
# Submit — add enterprise=1
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"version": "v3",
"enterprise": 1, # Required for Enterprise
"googlekey": sitekey,
"action": "login",
"pageurl": page_url
})
task_id = resp.text.split("|")[1]
# Polling is identical to standard
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY", "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
token = result.text.split("|")[1]
break
Универсальный решатель с автоопределением
Практичнее определять редакцию на лету — тогда переход сайта на Enterprise не требует правок.
import requests
import time
import re
class RecaptchaV3Solver:
def __init__(self, api_key):
self.api_key = api_key
def detect_and_solve(self, page_url, action=None):
"""Auto-detect standard vs enterprise and solve."""
html = requests.get(page_url).text
is_enterprise = "enterprise.js" in html
key_match = re.search(r'render[=:]\s*["\']?([A-Za-z0-9_-]{40})', html)
if not key_match:
raise Exception("No v3 sitekey found")
sitekey = key_match.group(1)
if not action:
action_match = re.search(r'action["\']?\s*[:=]\s*["\'](\w+)', html)
action = action_match.group(1) if action_match else "verify"
params = {
"key": self.api_key,
"method": "userrecaptcha",
"version": "v3",
"googlekey": sitekey,
"action": action,
"pageurl": page_url
}
if is_enterprise:
params["enterprise"] = 1
resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
if not resp.text.startswith("OK|"):
raise Exception(f"Submit failed: {resp.text}")
task_id = resp.text.split("|")[1]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key, "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
return result.text.split("|")[1]
if result.text != "CAPCHA_NOT_READY":
raise Exception(f"Solve failed: {result.text}")
raise Exception("Timed out")
solver = RecaptchaV3Solver("YOUR_API_KEY")
token = solver.detect_and_solve("https://staging.example.com/qa-login", action="login")
print(f"Token: {token[:40]}...")
Параметр action: главный источник отклонённых токенов
action — метка сценария, которую сайт передаёт в grecaptcha.execute(): login, checkout, register. Под каждую метку настраивается свой порог, и Enterprise делает это тоньше. Отправите не ту строку — токен вернётся исправно, но бэкенд даст низкий балл, а искать проблему вы будете в решателе.
Значения проще собрать прямо из HTML:
import re
def find_v3_actions(html):
"""Extract all action parameters from page JavaScript."""
# Look for grecaptcha.execute(key, {action: '...'})
pattern = r"(?:grecaptcha\.(?:enterprise\.)?execute|action)\s*[(:]\s*['\"](\w+)"
actions = re.findall(pattern, html)
return list(set(actions))
# Common actions: "login", "submit", "register", "checkout", "homepage"
Если совпадений несколько, берите метку открываемой страницы: login не подойдёт для формы оформления заказа.
Передача токена в форму
Дальше редакция не важна: результат кладётся в поле g-recaptcha-response.
# For browser-based workflows (Selenium)
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
# For pure HTTP workflows
requests.post(page_url, data={
"g-recaptcha-response": token,
"username": "user",
"password": "pass"
})
// Puppeteer
await page.evaluate((tok) => {
document.getElementById("g-recaptcha-response").value = tok;
}, token);
// Pure HTTP (axios)
await axios.post(pageUrl, new URLSearchParams({
"g-recaptcha-response": token,
username: "user",
password: "pass",
}));
Типичные ошибки
| Ошибка | Что происходит | Как исправить |
|---|---|---|
enterprise=1 на обычной v3 |
Токен может быть недействителен | Сначала проверьте enterprise.js |
Нет enterprise=1 на Enterprise |
Бэкенд отклоняет токен | Ставьте флаг при найденном enterprise.js |
Неверный action |
Низкий балл, отказ | Снимите точную строку из JS страницы |
Пропущен version=v3 |
Задача идёт как v2 | Указывайте version=v3 |
| Взят sitekey от v2 | ERROR_WRONG_GOOGLEKEY |
Ключ v3 берётся из render=KEY |
Сценарий: подрядчик, который не управляет сайтом
Типичная ситуация на аутсорсе: тесты гоняются на портале заказчика, доступа к Google Cloud Console нет, о переезде на Enterprise никто не предупредит. В понедельник прогон зелёный, в среду половина сценариев входа падает — хотя токены приходят как обычно.
Разбор занимает минуты, если автоопределение встроено: логируйте редакцию и action рядом с ID задачи — сразу видно, что изменилась страница, а не ваш код.
Цена от редакции не зависит: тарифы CaptchaAI считаются по числу параллельных потоков. Небольшому CI хватает BASIC ($15/мес, 5 потоков), ночным регрессам — ADVANCE ($90/мес, 50 потоков).
Если тесты попутно собирают данные, храните только то, что вправе обрабатывать: 152-ФЗ для российских заказчиков, GDPR — для трансграничных проектов.
Частые вопросы
Даёт ли Enterprise более низкий балл автоматизации?
Порог задаёт владелец сайта, а не версия. Enterprise позволяет выставить разные пороги под разные действия — сценарий проходит на главной и отсекается на входе. Токен формируется одинаково.
Что будет, если поставить enterprise=1 наугад?
Скорее всего, проверка не пройдёт: Enterprise валидирует токен через свой API и ждёт соответствующий токен; обратная ситуация ломается так же. Ставьте флаг только по результату проверки.
Как определить редакцию, если страница уже открыта в Selenium?
Отдельный запрос не нужен — смотрите в загруженный DOM:
page_source = driver.page_source
is_enterprise = "enterprise.js" in page_source
В Playwright тот же приём работает через page.content(), но только после полной загрузки скриптов.
Сайт вообще не отдаёт строку action — что делать?
Переберите частые значения: verify, submit, homepage, login. Если не помогло, найдите в DevTools вызов execute( — там строка видна явно.
Может ли сайт переключиться на Enterprise без предупреждения?
Да, регулярно. Поэтому определение редакции должно жить в рантайме, а не в конфиге — на это и рассчитан универсальный решатель выше; более широкий обзор — в полном разборе.
Что почитать дальше
- Enterprise против стандартной v3 — настройки со стороны сайта
- Полный разбор редакций reCAPTCHA — включая v2
- Решение reCAPTCHA v3 через API
- Решение reCAPTCHA v3 Enterprise через API
- Параметр action в reCAPTCHA v3 — как метки влияют на балл