Integrations

Retool + CaptchaAI: внутренний инструмент обработки форм CAPTCHA

Retool не умеет решать CAPTCHA сам: нужен внешний сервис, который принимает sitekey и pageurl, а возвращает токен. Ниже — схема на CaptchaAI штатными средствами Retool: один REST-ресурс, два запроса к API, JavaScript-запрос с циклом опроса и только потом интерфейс. На выходе приложение отдаёт готовый g-recaptcha-response для отправки формы.

Сценарий: заявки на визовый портал из внутренней панели

Типичная ситуация в агентстве из Алматы или Минска: операционная команда ведёт заявки клиентов в панели Retool, а подаёт их на портал с reCAPTCHA v2 — и оператор десятки раз за смену уходит решать проверку вручную. С этой интеграцией он остаётся в одном окне.

Работайте только с порталами, где у вас есть право подавать данные от имени клиента, и собирайте лишь те персональные данные, которые вправе обрабатывать (для читателей из РФ — с оглядкой на 152-ФЗ «О персональных данных»).

Шаг 1: заведите REST-ресурс CaptchaAI

В Retool откройте ResourcesCreate NewREST API:

Поле Значение
Name CaptchaAI
Base URL https://ocr.captchaai.com
Authentication нет — API-ключ передаётся параметром запроса

Сохраните ресурс: на него будут ссылаться оба следующих запроса.

Шаг 2: запрос отправки задачи

Создайте запрос submitCaptcha — метод GET, путь /in.php, ресурс CaptchaAI. Параметры:

Ключ Значение
key {{secretsStore.CAPTCHAAI_API_KEY}}
method userrecaptcha
googlekey {{sitekeyInput.value}}
pageurl {{pageurlInput.value}}
json 1

API-ключ храните в Secrets Store (SettingsSecrets): определения запросов видны всем, у кого есть доступ к редактору. Без json: 1 эндпоинт вернёт текст, а не JSON.

Трансформер (необязательный):

// Parse the response
const data = {{ submitCaptcha.data }};
if (data.status === 1) {
  return { taskId: data.request, status: 'submitted' };
}
return { error: data.request, status: 'failed' };

Шаг 3: запрос опроса результата

Создайте запрос pollResult — тоже GET, путь /res.php, тот же ресурс.

Ключ Значение
key {{secretsStore.CAPTCHAAI_API_KEY}}
action get
id {{submitCaptcha.data.request}}
json 1

Трансформер:

const data = {{ pollResult.data }};
if (data.status === 1) {
  return { token: data.request, status: 'solved' };
}
if (data.request === 'CAPCHA_NOT_READY') {
  return { status: 'pending' };
}
return { error: data.request, status: 'error' };

Ответ CAPCHA_NOT_READY — не ошибка, а промежуточное состояние; опечатка в слове входит в протокол.

Шаг 4: цикл опроса на JavaScript

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

// solveCaptcha — JavaScript Query
async function solve() {
  // Submit the CAPTCHA task
  await submitCaptcha.trigger();
  const submitResult = submitCaptcha.data;

  if (submitResult.status !== 1) {
    return { error: submitResult.request, status: 'submit_failed' };
  }

  const taskId = submitResult.request;

  // Wait 15 seconds before first poll
  await new Promise(r => setTimeout(r, 15000));

  // Poll up to 20 times (100 seconds max)
  for (let i = 0; i < 20; i++) {
    await pollResult.trigger({
      additionalScope: { taskId: taskId }
    });

    const result = pollResult.data;

    if (result.status === 1) {
      return { token: result.request, status: 'solved' };
    }

    if (result.request !== 'CAPCHA_NOT_READY') {
      return { error: result.request, status: 'error' };
    }

    // Wait 5 seconds before next poll
    await new Promise(r => setTimeout(r, 5000));
  }

  return { error: 'Polling timeout', status: 'timeout' };
}

return solve();

Цифры подобраны под лимит Retool: JavaScript-запрос живёт не дольше 120 секунд, а 15 + 20 × 5 укладывается в этот бюджет.

Шаг 5: соберите интерфейс

Ввод. Поля sitekeyInput («reCAPTCHA Sitekey») и pageurlInput («URL страницы»), кнопка solveButton («Решить CAPTCHA») с solveCaptcha.trigger() в onClick.

Статус. Текстовый компонент {{ solveCaptcha.isFetching ? "Solving..." : "" }} и индикатор загрузки при {{ solveCaptcha.isFetching }} — иначе оператор решит, что панель зависла, и нажмёт кнопку второй раз.

Результат. Поле tokenOutput только для чтения со значением {{ solveCaptcha.data?.token || '' }}, кнопка копирования и значок статуса по {{ solveCaptcha.data?.status }}.

Шаг 6: подставьте токен в отправку формы

Создайте запрос submitForm на целевой API: метод POST, в теле — данные формы с полем g-recaptcha-response: {{solveCaptcha.data.token}}. Кнопку «Отправить форму» держите неактивной до {{ solveCaptcha.data?.status === 'solved' }}: токен живёт недолго.

Что ломается чаще всего

Симптом Причина Что сделать
ERROR_WRONG_USER_KEY ключ не в Secrets Store или с опечаткой проверьте SettingsSecrets
Вместо JSON приходит текст потерян параметр json добавьте json: 1
Polling timeout типу CAPTCHA нужно больше времени увеличьте итерации с 20 до 30
submitCaptcha.dataundefined отправка ещё не отработала отправка должна идти до опроса
JavaScript-запрос обрывается лимит Retool в 120 секунд оставьте 20 итераций по 5 секунд

Сколько потоков закладывать

Тарификация — по числу одновременных задач (потоков), а не решений: в пределах плана решения не ограничены. Панели с ручным вводом хватает BASIC ($15/мес, 5 потоков) или STANDARD ($30/мес, 15 потоков); ADVANCE ($90/мес, 50 потоков) — для пакетной обработки.

Частые вопросы

Нужен ли отдельный бэкенд между Retool и CaptchaAI?

Нет. И облачный, и self-hosted Retool обращаются к ocr.captchaai.com напрямую — прослойка нужна лишь там, где политика безопасности запрещает исходящие запросы.

Что будет, если оператор нажмёт «Решить CAPTCHA» дважды подряд?

Уйдут две независимые задачи, и обе спишут поток на время решения. Поэтому кнопку стоит блокировать на {{ solveCaptcha.isFetching }}, а не полагаться на внимательность оператора.

Какие типы CAPTCHA поддерживаются, кроме reCAPTCHA v2?

Меняя method в submitCaptcha — reCAPTCHA v3, Cloudflare Turnstile, Cloudflare Challenge, GeeTest v3, текстовые и графические CAPTCHA. CaptchaFox, Friendly Captcha и Lemin — в статусе beta. hCaptcha и FunCaptcha не поддерживаются, GeeTest v4 заявлен как «скоро».

Почему первый опрос стоит откладывать на 15 секунд?

Раньше res.php почти всегда ответит CAPCHA_NOT_READY. Немедленный опрос не ускоряет решение, а лишь расходует итерации, которых из-за лимита немного.

Что делать, если токен не проходит на целевом сайте?

Сверьте sitekey и pageurl с тем, что отдаёт страница: чаще всего расходится домен — токен решён для одного адреса, а уходит на другой. Разбор параметров — в руководстве по reCAPTCHA v2.


Следующие шаги

Комментарии для этой статьи отключены.