Оба являются вариантами reCAPTCHA v2, использующими одну и ту же базовую технологию. Версия с флажком показывает «Я не робот» и может отображать сетки изображений. Невидимая версия срабатывает автоматически при действиях пользователя (нажатие кнопки, отправка формы или загрузка страницы) без видимого виджета. Единственная разница для решения CaptchaAI — это добавление invisible=1 к вашему запросу, но процесс передача токена во внутренний QA endpoint существенно отличается.
Параллельное сравнение
| Особенность | Флажок v2 | v2 Невидимый |
|---|---|---|
| Видимый виджет | Да — флажок «Я не робот» | Нет — скрыто от пользователей |
| Спусковой механизм | Пользователь нажимает флажок | Нажатие кнопки, отправка формы или загрузка страницы |
| Задача изображения | Отображается, когда Google подозревает бота | Всплывающее окно в правом нижнем углу при подозрении |
| Пользовательский опыт | Умеренное трение | Низкое трение/zero |
| Выполнение | Добавить div g-recaptcha на страницу |
Добавьте data-callback к кнопке или grecaptcha.execute(). |
| Формат ключа сайта | То же, что невидимка | То же, что флажок |
| Поле токена | g-recaptcha-response |
g-recaptcha-response |
| Функция обратного вызова | Необязательный | Почти всегда требуется |
| Метод CaptchaAI | method=userrecaptcha |
method=userrecaptcha + invisible=1 |
| Срок действия токена | 120 секунд | 120 секунд |
| Решить время | 10-30 секунд | 10–25 секунд |
Как каждый из них отображается в HTML
Флажок v2
<!-- Standard checkbox widget -->
<div class="g-recaptcha"
data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
data-callback="onSubmit">
</div>
<!-- Widget renders as: -->
<!-- [✓] I'm not a robot reCAPTCHA logo -->
Пользователь видит флажок и взаимодействует с ним. Если у Google возникнут подозрения, в строке появится запрос на сетку изображений.
v2 Невидимый
<!-- Pattern 1: Invisible widget on a button -->
<button class="g-recaptcha"
data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
data-callback="onSubmit"
data-size="invisible">
Submit
</button>
<!-- Pattern 2: Invisible div (programmatic trigger) -->
<div class="g-recaptcha"
data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
data-size="invisible"
data-callback="onSubmit">
</div>
<!-- Pattern 3: Programmatic render -->
<script>
grecaptcha.render('submit-btn', {
sitekey: '6Le-wvkSAAAAAPBMRTvw...',
callback: onSubmit,
size: 'invisible'
});
</script>
Нет видимого виджета. reCAPTCHA активируется, когда пользователь запускает указанный элемент или когда вызывается grecaptcha.execute().
Как определить, какой вариант находится на странице
Обнаружение Python:
import requests
from bs4 import BeautifulSoup
import re
def detect_recaptcha_variant(url):
resp = requests.get(url)
soup = BeautifulSoup(resp.text, "html.parser")
# Check for invisible indicators
invisible_widget = soup.find(attrs={"data-size": "invisible", "class": "g-recaptcha"})
if invisible_widget:
return {
"variant": "invisible",
"sitekey": invisible_widget.get("data-sitekey"),
"callback": invisible_widget.get("data-callback")
}
# Check for programmatic invisible in scripts
for script in soup.find_all("script"):
if script.string and "invisible" in str(script.string):
key_match = re.search(r"sitekey['\"]?\s*[:=]\s*['\"]([^'\"]+)", script.string)
if key_match:
return {
"variant": "invisible-programmatic",
"sitekey": key_match.group(1),
"callback": "check grecaptcha.render() call"
}
# Check for standard checkbox
checkbox_widget = soup.find(class_="g-recaptcha")
if checkbox_widget:
return {
"variant": "checkbox",
"sitekey": checkbox_widget.get("data-sitekey"),
"callback": checkbox_widget.get("data-callback")
}
return None
result = detect_recaptcha_variant("https://https://staging.example.com/qa-login")
print(result)
Обнаружение Node.js:
const axios = require("axios");
const cheerio = require("cheerio");
async function detectRecaptchaVariant(url) {
const { data } = await axios.get(url);
const $ = cheerio.load(data);
// Check for invisible
const invisible = $(".g-recaptcha[data-size='invisible']");
if (invisible.length) {
return {
variant: "invisible",
sitekey: invisible.attr("data-sitekey"),
callback: invisible.attr("data-callback"),
};
}
// Check scripts for programmatic invisible
const scripts = $("script")
.map((_, el) => $(el).html())
.get()
.join("\n");
if (scripts.includes("invisible")) {
const keyMatch = scripts.match(/sitekey['"]?\s*[:=]\s*['"]([^'"]+)/);
if (keyMatch) {
return {
variant: "invisible-programmatic",
sitekey: keyMatch[1],
callback: "check render call",
};
}
}
// Check for standard checkbox
const checkbox = $(".g-recaptcha");
if (checkbox.length) {
return {
variant: "checkbox",
sitekey: checkbox.attr("data-sitekey"),
callback: checkbox.attr("data-callback"),
};
}
return null;
}
Быстрая проверка консоли браузера:
const el = document.querySelector('[data-size="invisible"]');
console.log(el ? "Invisible reCAPTCHA" : "Checkbox reCAPTCHA");
| Сигнал обнаружения | Флажок v2 | v2 Невидимый |
|---|---|---|
data-size="invisible" |
Нет | Подарок |
| Видимый флажок на странице | Да | Нет |
grecaptcha.execute() позвонил |
Нет (пользователь нажимает) | Да (программный) |
| Позиция всплывающего окна вызова | Встроенное, под флажком | Правый нижний угол страницы |
Решение с помощью CaptchaAI
Флажок v2
import requests
import time
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": "6Le-wvkSAAAA...",
"pageurl": "https://example.com/form"
})
task_id = resp.text.split("|")[1]
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
v2 Невидимый
import requests
import time
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": "6Le-wvkSAAAA...",
"pageurl": "https://example.com/form",
"invisible": 1 # Only parameter difference
})
task_id = resp.text.split("|")[1]
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
передача токена во внутренний QA endpoint — критическая разница
Флажок v2: обычно достаточно скрытого поля.
# Selenium — inject into hidden field
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
# If the page uses a callback, also call it
callback = driver.find_element("css selector", ".g-recaptcha").get_attribute("data-callback")
if callback:
driver.execute_script(f'{callback}("{token}");')
v2 Invisible: обратный вызов требуется почти всегда.
# Selenium — inject AND call the callback
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
# CRITICAL: Invisible reCAPTCHA almost always requires calling the callback
callback_name = driver.find_element(
"css selector", ".g-recaptcha[data-size='invisible']"
).get_attribute("data-callback")
driver.execute_script(f'{callback_name}("{token}");')
// Puppeteer — invisible callback injection
await page.evaluate((tok) => {
// Set the hidden field
document.getElementById("g-recaptcha-response").value = tok;
// Find and call the callback function
const widget = document.querySelector("[data-size='invisible']");
const cbName = widget?.getAttribute("data-callback");
if (cbName && typeof window[cbName] === "function") {
window[cbName](tok);
}
}, token);
Ключевое отличие: Формы флажков версии 2 часто работают только с внедрением скрытых полей, поскольку щелчок пользователя по флажку уже зарегистрировал обратный вызов. В невидимой reCAPTCHA такого щелчка никогда не происходит — обратный вызов должен вызываться явно.
Универсальный решатель для обоих вариантов
import requests
import time
from bs4 import BeautifulSoup
class RecaptchaV2UniversalSolver:
def __init__(self, api_key):
self.api_key = api_key
def detect_and_solve(self, page_url, page_html=None):
if not page_html:
page_html = requests.get(page_url).text
soup = BeautifulSoup(page_html, "html.parser")
# Detect variant
invisible = soup.find(attrs={"data-size": "invisible", "class": "g-recaptcha"})
widget = invisible or soup.find(class_="g-recaptcha")
if not widget:
raise Exception("No reCAPTCHA widget found")
sitekey = widget.get("data-sitekey")
is_invisible = invisible is not None
callback = widget.get("data-callback")
params = {
"key": self.api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url
}
if is_invisible:
params["invisible"] = 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 {
"token": result.text.split("|")[1],
"variant": "invisible" if is_invisible else "checkbox",
"callback": callback,
"sitekey": sitekey
}
if result.text != "CAPCHA_NOT_READY":
raise Exception(f"Solve error: {result.text}")
raise Exception("Timed out")
# Usage
solver = RecaptchaV2UniversalSolver("YOUR_API_KEY")
result = solver.detect_and_solve("https://https://staging.example.com/qa-login")
print(f"Variant: {result['variant']}, Callback: {result['callback']}")
Поиск неисправностей
| Проблема | Исправление флажка | Невидимое исправление |
|---|---|---|
| Токен не принят | Внедрить в поле g-recaptcha-response |
Внедрить И вызвать функцию data-callback |
| Виджет не найден | Найдите класс .g-recaptcha. |
Проверьте наличие data-size="invisible" или вызовов рендеринга сценария. |
| Форма отправляется, но не получается | Проверьте, ожидается ли обратный звонок | Обратный звонок требуется практически всегда — найдите и позвоните |
| Страница перезагружается после инъекции | Проверка JavaScript не удалась | Вызов обратного вызова перед формой триггеров автоматической отправки |
Часто задаваемые вопросы
Сложнее ли решить невидимую reCAPTCHA?
Нет. Процесс решения с помощью CaptchaAI практически идентичен. Единственное изменение — добавление invisible=1 к вашему запросу. Дополнительная задача связана с внедрением: вы должны найти и выполнить функцию обратного вызова.
Оба используют один и тот же формат sitekey?
Да. Формат sitekey идентичен. Вы не можете определить вариант только по ключу сайта — проверьте наличие data-size="invisible" в HTML.
Невидимая reCAPTCHA по-прежнему показывает проблемы с изображением?
Да. Когда Google обнаруживает подозрительное поведение, невидимая reCAPTCHA отображает всплывающее окно с изображением в правом нижнем углу страницы. Вот почему вам все еще нужен CaptchaAI — невидимая версия все еще может представлять проблемы.
Может ли сайт переключаться между флажком и невидимостью?
Да. Это изменение конфигурации на стороне сайта — тот же ключ сайта, другая реализация. Некоторые сайты используют флажок на рабочем столе и невидим на мобильном устройстве. Всегда обнаруживайте вариант динамически.
Что быстрее решить?
Невидимые решения обычно выполняются немного быстрее (10–25 секунд против 10–30 секунд), поскольку они, как правило, вызывают меньше проблем с изображением. Но разница незначительна.
Связанные руководства
- Как решить reCAPTCHA v2 с помощью API— полное руководство по флажкам версии 2
- Как работает reCAPTCHA Invisible— объяснение невидимого механизма
- Как решить reCAPTCHA Invisible с помощью API— невидимый учебник по решению
- Распространенные ошибки и исправления reCAPTCHA Invisible— невидимое устранение неполадок
- Как решить reCAPTCHA Invisible с помощью API
- Как работает reCAPTCHA Invisible
- Объяснение reCAPTCHA v2 против v3