Чтобы CaptchaAI решил reCAPTCHA, от вас нужны всего два обязательных значения — sitekey и pageurl. Дальше начинаются нюансы по версии: v3 требует action, часть сайтов Google передаёт data-s, а reCAPTCHA Enterprise добавляет отдельный флаг. Если параметр найден неверно или устарел, API либо вернёт ошибку, либо отдаст «успешный» токен, который сайт всё равно отклонит на форме.
Четыре рабочих способа вытащить параметры из исходного кода страницы, от самого простого к самому надёжному:
- HTML-атрибуты виджета — быстрее всего, но работает только если виджет уже в разметке.
- URL скрипта и вызовы JS — нужен для v3 и Enterprise, где sitekey не лежит в HTML.
srciframe — запасной вариант, когда виджет встроен как отдельный документ.- Рендеринг через
grecaptcha.render()— единственный надёжный путь для страниц, которые собирают виджет полностью на клиенте.
Держите под рукой оба инструмента:
reдля статичной разметки и headless-браузер (Puppeteer/Selenium) для всего, что рисуется JavaScript уже после загрузки страницы.
Для каждого способа ниже — пример на Python и один на Puppeteer.
Способ 1: извлечение атрибутов HTML
Из атрибута data-sitekey
Большинство сайтов рендерят виджет reCAPTCHA v2 прямо в исходном HTML, поэтому sitekey вытаскивается обычным regex без запуска браузера:
import re
import requests
url = "https://staging.example.com/qa-login"
html = requests.get(url).text
# Find data-sitekey
match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]+)["\']', html)
if match:
sitekey = match.group(1)
print(f"Sitekey: {sitekey}")
# Check if invisible
invisible_match = re.search(r'data-size=["\']invisible["\']', html)
is_invisible = bool(invisible_match)
print(f"Invisible: {is_invisible}")
# Find callback
callback_match = re.search(r'data-callback=["\'](\w+)["\']', html)
callback = callback_match.group(1) if callback_match else None
print(f"Callback: {callback}")
# Check for data-s (Google-owned sites)
data_s_match = re.search(r'data-s=["\']([^"\']+)["\']', html)
data_s = data_s_match.group(1) if data_s_match else None
print(f"data-s: {data_s}")
Если data-size вернул invisible, виджет невидимый и отправка формы обычно идёт через JS-callback, а не через клик по чекбоксу — это не меняет набор параметров для CaptchaAI, но объясняет, почему на странице не видно самого виджета.
JavaScript (Puppeteer)
Когда сайт дорисовывает виджет через JS уже после загрузки и в исходном HTML атрибутов ещё нет, статический regex ничего не найдёт — нужен настоящий браузер:
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://staging.example.com/qa-login', { waitUntil: 'networkidle2' });
const params = await page.evaluate(() => {
const widget = document.querySelector('.g-recaptcha');
if (!widget) return null;
return {
sitekey: widget.getAttribute('data-sitekey'),
size: widget.getAttribute('data-size'),
callback: widget.getAttribute('data-callback'),
dataS: widget.getAttribute('data-s'),
invisible: widget.getAttribute('data-size') === 'invisible',
};
});
console.log(params);
Способ 2. Извлечение тегов сценария.
reCAPTCHA v3 и ключи корпоративного сайта
Sitekey у v3 живёт не в разметке, а в URL самого скрипта:
# Find sitekey from script src
v3_match = re.search(
r'recaptcha/(?:api|enterprise)\.js\?.*?render=([A-Za-z0-9_-]+)',
html
)
if v3_match:
sitekey = v3_match.group(1)
print(f"v3 Sitekey: {sitekey}")
# Check enterprise
is_enterprise = 'enterprise.js' in html
print(f"Enterprise: {is_enterprise}")
Нахождение параметра действия
action передаётся аргументом вызова grecaptcha.execute() в JS-коде страницы, а не HTML-атрибутом — искать нужно в теле скрипта:
# Search for grecaptcha.execute calls
action_match = re.search(
r'grecaptcha\.execute\s*\([^,]+,\s*\{[^}]*action\s*:\s*["\']([^"\']+)',
html
)
if action_match:
action = action_match.group(1)
print(f"Action: {action}")
Частые причины, по которым action не находится с первой попытки:
- значение задано во внешнем
.js-файле, а не в инлайн-скрипте на странице; - на странице несколько вызовов
grecaptcha.execute()подряд, и regex цепляет не тот; - фронтенд генерирует
actionдинамически (например, из имени текущего роута).
Способ 3: извлечение Iframe src
Если reCAPTCHA рендерится внутри iframe (частый случай на страницах логина со сторонними виджетами), sitekey находится в query-параметре k= внутри src:
# Find reCAPTCHA iframe
iframe_match = re.search(
r'<iframe[^>]+src=["\']([^"\']*recaptcha/api2/anchor[^"\']*)["\']',
html
)
if iframe_match:
iframe_src = iframe_match.group(1)
sitekey_match = re.search(r'k=([A-Za-z0-9_-]+)', iframe_src)
if sitekey_match:
sitekey = sitekey_match.group(1)
print(f"Iframe sitekey: {sitekey}")
Iframe-путь обычно всплывает, когда виджет встроен через сторонний скрипт-загрузчик, а не подключён на самой странице напрямую — например, виджет, который подгружает партнёрская форма оплаты или логина.
Метод 4: извлечение рендеринга JavaScript
Часть страниц вызывает grecaptcha.render() программно уже после загрузки DOM — до выполнения скрипта параметры вообще не появляются в исходном HTML:
# Find grecaptcha.render calls
render_match = re.search(
r'grecaptcha\.render\s*\([^,]*,\s*\{([^}]+)\}',
html
)
if render_match:
config = render_match.group(1)
sk = re.search(r'sitekey\s*:\s*["\']([A-Za-z0-9_-]+)', config)
cb = re.search(r'callback\s*:\s*["\']?(\w+)', config)
sz = re.search(r'size\s*:\s*["\'](\w+)', config)
print(f"Sitekey: {sk.group(1) if sk else 'not found'}")
print(f"Callback: {cb.group(1) if cb else 'not found'}")
print(f"Size: {sz.group(1) if sz else 'not found'}")
Сводная таблица: какие параметры нужны для каждой версии
После того как вы прошли все четыре способа, держите эту таблицу под рукой как чек-лист перед отправкой задачи в CaptchaAI — она показывает, каких полей не хватает для конкретной версии:
| Параметр | v2 Standard | v2 Invisible | v3 | Enterprise |
|---|---|---|---|---|
googlekey (sitekey) |
Обязателен | Обязателен | Обязателен | Обязателен |
pageurl |
Обязателен | Обязателен | Обязателен | Обязателен |
invisible |
— | 1 |
— | — |
action |
— | — | Обязателен | Иногда |
data-s |
Иногда | Иногда | — | — |
enterprise |
— | — | — | 1 |
Полная функция извлечения
Собрать все четыре способа в один хелпер, который перебирает варианты по порядку и возвращает первый найденный результат, — самый практичный вариант для CI и QA-пайплайнов:
import re
import requests
def extract_recaptcha_params(url):
html = requests.get(url, timeout=15).text
params = {"pageurl": url}
# Sitekey from data-sitekey
sk = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]+)', html)
if sk:
params["sitekey"] = sk.group(1)
# Sitekey from script render parameter (v3)
if "sitekey" not in params:
v3 = re.search(r'render=([A-Za-z0-9_-]{20,})', html)
if v3:
params["sitekey"] = v3.group(1)
# Sitekey from iframe
if "sitekey" not in params:
iframe = re.search(r'recaptcha.*?k=([A-Za-z0-9_-]+)', html)
if iframe:
params["sitekey"] = iframe.group(1)
# Sitekey from grecaptcha.render
if "sitekey" not in params:
render = re.search(r'sitekey\s*:\s*["\']([A-Za-z0-9_-]+)', html)
if render:
params["sitekey"] = render.group(1)
# Version detection
if re.search(r'data-size=["\']invisible', html):
params["invisible"] = True
if 'enterprise.js' in html:
params["enterprise"] = True
# Action (v3)
action = re.search(
r'action\s*:\s*["\']([^"\']+)',
html[html.find('grecaptcha.execute'):] if 'grecaptcha.execute' in html else ''
)
if action:
params["action"] = action.group(1)
# data-s
ds = re.search(r'data-s=["\']([^"\']+)', html)
if ds:
params["data_s"] = ds.group(1)
# Callback
cb = re.search(r'data-callback=["\'](\w+)', html)
if cb:
params["callback"] = cb.group(1)
return params
# Usage
params = extract_recaptcha_params("https://staging.example.com/qa-login")
for k, v in params.items():
print(f" {k}: {v}")
Ожидаемый результат:
pageurl: https://staging.example.com/qa-login
sitekey: 6Le-SITEKEY-abc123
invisible: True
callback: onCaptchaComplete
Отправка извлеченных параметров в CaptchaAI
После того как sitekey и остальные значения найдены, они почти без изменений подставляются в запрос к in.php — CaptchaAI сам определяет нужный тип решения по набору переданных полей:
data = {
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": params["sitekey"],
"pageurl": params["pageurl"],
"json": "1",
}
if params.get("invisible"):
data["invisible"] = "1"
if params.get("enterprise"):
data["enterprise"] = "1"
if params.get("action"):
data["action"] = params["action"]
if params.get("data_s"):
data["data-s"] = params["data_s"]
resp = requests.post("https://ocr.captchaai.com/in.php", data=data).json()
Что делать, если параметры не находятся
Если ни один из четырёх способов не сработал с первого раза, проверьте по порядку:
- Sitekey не найден вообще — страница рендерит виджет динамически. Переключитесь со статического HTML на Puppeteer или Selenium (Способ 1, второй пример).
- Найденный sitekey не тот — на странице несколько экземпляров reCAPTCHA. Сверьтесь с DOM и убедитесь, что берёте атрибуты виджета, привязанного именно к нужной форме.
actionне находится — значение задано во внешнем JS-файле, а не в инлайн-скрипте. Подгрузите и просканируйте связанные.js-файлы отдельно.data-sперестал совпадать при повторном запросе — Google периодически перевыпускает это значение для одного и того же sitekey. Извлекайтеdata-sзаново перед каждым решением, не кешируйте его.
Пример: экстрактор в CI для QA-тестирования форм
Для агентств и фрилансеров, которые ведут несколько проектов на разных стеках одновременно (Node.js у одного клиента, Python у другого), типичный сценарий — держать этот экстрактор отдельным модулем и гонять его в CI перед каждым деплоем формы логина или регистрации на staging. Если клиент обновил виджет и sitekey поменялся, тест падает раньше, чем это заметят на проде, а не после жалоб пользователей. При таком объёме проверок — десятки или сотни запросов в день на нескольких стендах параллельно — тарификация по потокам, а не по решению, снимает вопрос «сколько стоит один непойманный sitekey»: на плане BASIC ($15/мес, 5 потоков) можно одновременно гонять до пяти таких проверок, не считая каждый вызов отдельно.
Часто задаваемые вопросы
Обязательно ли поднимать браузер, чтобы найти параметры reCAPTCHA?
Нет — для большинства сайтов sitekey лежит прямо в исходном HTML, и regex справляется без браузера. Но если виджет дорисовывается через JavaScript уже после загрузки страницы (Способ 1, второй пример), понадобится headless-браузер вроде Puppeteer или Selenium.
Чем sitekey отличается от API-ключа CaptchaAI?
Это разные вещи. Sitekey — публичный идентификатор, привязанный к конкретному сайту; он открыт всем и виден прямо в исходном коде страницы. API-ключ CaptchaAI — приватный, привязан к вашему аккаунту и не должен появляться нигде в клиентском коде.
Можно ли использовать один и тот же экстрактор для reCAPTCHA v2 и v3?
Да — полная функция извлечения перебирает оба случая по порядку и берёт первый найденный sitekey, независимо от версии. Главное отличие в обработке результата: у v3 нет видимого чекбокса, так что и решение, и последующий callback обрабатываются полностью на стороне JS, без клика пользователя.
Нужно ли передавать data-s, если на сайте его нет в разметке?
Нет. Поле data-s встречается только на части сайтов, использующих инфраструктуру Google, и его нужно передавать в CaptchaAI, только если оно реально присутствует в HTML. Отправка пустого значения ничего не даёт и может сбить обработку запроса.
Что делать, если reCAPTCHA рендерится внутри shadow DOM?
Обычный querySelector и regex по HTML не видят содержимое shadow DOM. В Puppeteer или Playwright нужно явно обратиться к shadowRoot элемента-хоста, прежде чем искать атрибуты виджета; для чисто статического парсинга HTML такой виджет извлечь не получится в принципе — здесь без браузера не обойтись.
Как проверить, что найденный action соответствует реальной форме?
Если на странице несколько вызовов grecaptcha.execute() (например, отдельно для логина и для формы обратной связи), возьмите значение action из вызова, который срабатывает именно при отправке нужной вам формы — обычно это ближайший grecaptcha.execute к обработчику submit в том же скрипте.
Подключите извлечённые параметры к CaptchaAI
Зарегистрируйтесь и получите API-ключ на captchaai.com, затем передайте найденные sitekey, pageurl и опциональные параметры в in.php — как показано выше.
Связанные руководства
- Обнаружение CAPTCHA в консоли браузера
- Механизм обратного вызова reCAPTCHA v2
- Триггер невидимой reCAPTCHA v2: как его обнаружить