Как исправить ERROR_GOOGLEKEY и ERROR_PAGEURL при отправке

Короткий ответ: ERROR_GOOGLEKEY означает, что отклонено значение googlekey , которое вы отправили, а ERROR_PAGEURL означает, что отклонено значение pageurl . Оба ответа приходят от /in.php на этапе отправки, поэтому задача не создана и опрашивать нечего. В девяти случаях из десяти причина в имени параметра: reCAPTCHA ждёт googlekey, а Turnstile ждёт sitekey. Отправите не то, получите ровно это. Ниже о том, как их различать и как исправить каждую.
Что на самом деле проверяют эти два кода
| Код | Значение по документации | Какой параметр |
|---|---|---|
ERROR_GOOGLEKEY | Некорректно googlekey параметр указан неверно | Sitekey, считанный со страницы |
ERROR_PAGEURL | Некорректно pageurl параметр указан неверно | URL страницы, на которой стоит виджет |
Это ошибки валидации, а не ошибки решения. Ничего ещё не пробовали решать, и в очереди ничего нет.
Этап отправки, а не этап опроса
Это различие экономит массу времени на отладке. У API два этапа, и у каждого своё семейство ошибок.
# Stage 1: submit. These codes appear HERE. curl -X POST http://127.0.0.1:8080/in.php \ -d "key=YOUR_API_KEY" -d "method=userrecaptcha" \ -d "sitekey=YOUR_SITEKEY" \ -d "pageurl=https://example.com/page-with-recaptcha" ERROR_GOOGLEKEY # no ID came back, so there is nothing to poll
Сравните с нормальной отправкой, которая возвращает OK|2122988149 и падает, если вообще падает, уже на /res.php. Сбой на этапе опроса означает, что параметры приняли, а решить не удалось: это совсем другое расследование. Смотрите ERROR_CAPTCHA_UNSOLVABLE про этот случай и ERROR_KEY_DOES_NOT_EXIST , если сам ключ отклоняют ещё до обеих проверок.
Почему значение отклоняют
Почти всё сводится к трём причинам, в таком порядке.
Причина первая: googlekey против sitekey
Совместимый с 2captcha API использует своё имя параметра для каждого метода, и они не взаимозаменяемы.
| Метод | Параметр ключа | Неверное имя даёт |
|---|---|---|
userrecaptcha | googlekey | ERROR_GOOGLEKEY |
turnstile | sitekey | ERROR_BAD_PARAMETERS |
geetest | gt плюс challenge | ERROR_BAD_PARAMETERS |
Ловушка в том, что в разговоре это значение все называют sitekey, да и HTML-атрибут буквально называется data-sitekey и у reCAPTCHA, и у Turnstile. Только параметр отправки для reCAPTCHA назван в честь Google. Если вы скопировали рабочий вызов Turnstile и поменяли method в userrecaptcha, вот вам и баг.
SDK полностью скрывают эту разницу. solver.recaptcha(sitekey, url) и solver.turnstile(sitekey, url) принимают одинаковый первый аргумент и сами подставляют нужное имя в запросе, а это хороший повод ими пользоваться.
Причина вторая: ключ устарел, обрезан или пуст
Если имя параметра верное, следующий подозреваемый это само значение.
- Вы зашили его в код. Сайты меняют sitekey. Константа, работавшая в прошлом месяце, сегодня может быть мертва.
- Он взят из кешированного исходника страницы. Просмотр исходного кода в браузере может отдать копию старее той, из которой реально отрисовался виджет.
- Вы взяли не тот атрибут. Значение лежит в
data-sitekey, а не вid,nameили в атрибуте iframetitle. - Переменная оболочки притащила с собой перевод строки. Подстановка команды сохраняет хвостовые пробелы, а пробел не входит в валидный ключ.
- Оно пустое. Неустановленная переменная разворачивается в пустоту, и запрос уходит с
googlekey=.
Читайте его из живого DOM, а не доверяйте константе:
// Run in the page, or via your automation tool's evaluate().
// reCAPTCHA and Turnstile both expose it as data-sitekey.
const recaptchaKey = document.querySelector('.g-recaptcha')?.dataset.sitekey;
const turnstileKey = document.querySelector('.cf-turnstile')?.dataset.sitekey;
// Fallback: reCAPTCHA also carries it as k= in the widget iframe URL.
const iframe = document.querySelector('iframe[src*="/recaptcha/"]');
const fromSrc = iframe ? new URL(iframe.src).searchParams.get('k') : null;
console.log(recaptchaKey || fromSrc);The k= нужен на сайтах, которые рисуют виджет через JavaScript и не оставляют элемент .g-recaptcha в DOM.
Причина третья: из-за чего pageurl считается неверным
ERROR_PAGEURL проблема более узкая и обычно механическая.
- Нет схемы.
example.com/loginэто не URL. Отправляйтеhttps://example.com/login. - Относительный путь.
/loginэто то, что было под рукой у вашего скрапера, а не то, что нужно API. - Обрезание в GET. Если URL страницы содержит собственную query-строку и вы отправляете GET без кодирования, всё после первого амперсанда разбирается как параметр вашего же вызова API. Используйте POST или
--data-urlencode. - Пробелы или кавычки. URL, прочитанный из конфига, может приехать в кавычках, которые никто не снял.
URL не обязан быть доступен с машины, где работает CapSkip, и это не обязательно тот URL, куда вы в итоге отправите форму. Это должна быть страница, в которую встроен виджет, потому что именно к ней привязывается токен.
Как это выглядит из SDK
SDK ловят очевидные проблемы ещё до того, как что-то покинет ваш процесс, а остальное пропускают дальше. Два разных исключения, два разных решения.
# pip install capskip
from capskip import CapSkip, ApiException, ValidationException
solver = CapSkip(host="127.0.0.1", port=8080)
try:
result = solver.recaptcha(
sitekey=sitekey_from_dom,
url="https://example.com/page-with-recaptcha",
)
except ValidationException:
# Caught locally: empty sitekey, malformed URL, missing argument.
print("fix the values before sending")
except ApiException as e:
# Came back from the API: GOOGLEKEY or PAGEURL rejected.
print(f"rejected at submit: {e}")A ValidationException означает, что до API вы вообще не дошли. А ApiException с одним из этих кодов означает, что дошли и значение отвергли. Тот же подход в C#, только работу делает базовый тип:
using CapSkip;
var solver = new CapSkipClient(host: "127.0.0.1", port: 8080);
try
{
var result = await solver.RecaptchaAsync(sitekey, pageUrl);
}
catch (ApiException ex)
{
// ERROR_GOOGLEKEY or ERROR_PAGEURL arrives here.
Console.WriteLine(ex.Message);
}
catch (CapSkipError ex)
{
// Everything else the SDK can throw.
Console.WriteLine(ex.Message);
}Чек-лист на две минуты
- Выведите точное тело запроса, которое отправляете. Не переменные, а именно тело.
- Сверьте имя параметра с методом:
googlekeyдля reCAPTCHA,sitekeyдля Turnstile. - Убедитесь, что значение не пустое и без хвостового перевода строки.
- Перечитайте sitekey с живой страницы и сравните с отправленным.
- Убедитесь, что
pageurlначинается сhttp://илиhttps://. - Переключите вызов на POST, если в URL страницы есть query-строка.
Первый пункт решает проблему чаще, чем остальные пять вместе взятые: расхождение обычно между тем, что вы думаете, что отправляете, и тем, что реально уходит в сеть.
Соседние коды и что означают они
| Код | Означает |
|---|---|
ERROR_WRONG_USER_KEY | API-ключ отсутствует или пуст; проверяется раньше обоих |
ERROR_WRONG_METHOD | The method или action не из тех, что известны API |
ERROR_BAD_PARAMETERS | Обязательного для этого метода параметра нет вовсе |
ERROR_CAPTCHA_UNSOLVABLE | Отправка прошла, решение нет. Этап опроса, а не отправки |
CAPCHA_NOT_READY | Не ошибка. Продолжайте опрашивать тот же ID |
Все коды с точными формулировками перечислены в Документация по API.
Часто задаваемые вопросы
Стоит ли повторять запрос после ERROR_GOOGLEKEY?
Нет. Те же значения будут отклоняться одинаково каждый раз, поэтому цикл повторов только тратит время и прячет настоящую проблему. Исправьте значение и отправьте один раз. Повтор уместен при сбое на этапе опроса, а не отправки.
Sitekey верный, но его всё равно отклоняют. Что дальше?
Сначала ищите невидимые повреждения: хвостовой перевод строки от подстановки команды, кавычки из конфига или значение, обрезанное колонкой фиксированной ширины в базе. Выведите длину строки, которую отправляете. Стандартный sitekey reCAPTCHA это 40 символов, так что всё, что короче, где-то обрезали.
Должен ли pageurl быть доступен извне?
Нет. Он указывает, какой странице принадлежит виджет, поэтому страница за логином вполне подходит. Чем он быть не может, так это заглушкой: другой домен вместо того, где стоит виджет, даст токен, который сайт отвергнет, даже если отправка прошла успешно.
Возвращает ли решение Turnstile ошибку ERROR_GOOGLEKEY?
Не должно, потому что метод turnstile вообще не читает параметр googlekey . Если она приходит на вызов Turnstile, почти всегда это значит, что method всё ещё равен userrecaptcha из скопированного запроса. Исправьте метод, затем отправляйте sitekey а не googlekey.
Сводка
Относитесь к error_googlekey и ERROR_PAGEURL как опечатки, а не как сбои. Задача не создана, попытки не было, повторять нечего. Сверьте имя параметра с методом, читайте sitekey из живого DOM вместо константы и отправляйте URL страницы вместе со схемой. Полные таблицы параметров для каждого метода есть на странице Решатель reCAPTCHA .
Отлаживать это дёшево, когда у вас безлимитный сервис распознавания капчи , работающий локально. Отклонённые отправки не сжигают кредиты и не расходуют квоту, так что можно отправить один и тот же запрос двадцать раз, пока не найдёте неверный символ.
