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

error_googlekey - How to Fix ERROR_GOOGLEKEY and ERROR_PAGEURL on Submit

Короткий ответ: 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 использует своё имя параметра для каждого метода, и они не взаимозаменяемы.

МетодПараметр ключаНеверное имя даёт
userrecaptchagooglekeyERROR_GOOGLEKEY
turnstilesitekeyERROR_BAD_PARAMETERS
geetestgt плюс challengeERROR_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 или в атрибуте iframe title.
  • Переменная оболочки притащила с собой перевод строки. Подстановка команды сохраняет хвостовые пробелы, а пробел не входит в валидный ключ.
  • Оно пустое. Неустановленная переменная разворачивается в пустоту, и запрос уходит с 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);
}

Чек-лист на две минуты

  1. Выведите точное тело запроса, которое отправляете. Не переменные, а именно тело.
  2. Сверьте имя параметра с методом: googlekey для reCAPTCHA, sitekey для Turnstile.
  3. Убедитесь, что значение не пустое и без хвостового перевода строки.
  4. Перечитайте sitekey с живой страницы и сравните с отправленным.
  5. Убедитесь, что pageurl начинается с http:// или https://.
  6. Переключите вызов на POST, если в URL страницы есть query-строка.

Первый пункт решает проблему чаще, чем остальные пять вместе взятые: расхождение обычно между тем, что вы думаете, что отправляете, и тем, что реально уходит в сеть.

Соседние коды и что означают они

КодОзначает
ERROR_WRONG_USER_KEYAPI-ключ отсутствует или пуст; проверяется раньше обоих
ERROR_WRONG_METHODThe 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 .

Отлаживать это дёшево, когда у вас безлимитный сервис распознавания капчи , работающий локально. Отклонённые отправки не сжигают кредиты и не расходуют квоту, так что можно отправить один и тот же запрос двадцать раз, пока не найдёте неверный символ.