先说结论:别试图在 Retool 里渲染 reCAPTCHA v2 小部件。查询跑在服务端,没有能加载 Google 验证码脚本的浏览器上下文。可行做法是把 sitekey 和页面 URL 交给识别接口,拿回 token,让下游那条提交请求带着它走。
在 Retool 上,这条链就是一个 REST API 资源、两个 GET 查询、一个负责轮询的 JavaScript 查询,界面五个组件收尾。
前置准备
- Retool 账号:Cloud 与自托管版都支持 REST API 资源和 JS 查询
- CaptchaAI 账号与 API Key
- sitekey:一般在页面源码的
data-sitekey属性里 - 验证码所在页的完整 URL:填首页无效
整条链四步:读入 sitekey 与页面 URL,submitCaptcha 提交任务,solveCaptcha 轮询取回 token,submitForm 带着 token 提交表单。
适用范围: 仅限你自己拥有或已获授权的门户系统,并遵守 robots 协议与《网络安全法》相关要求。
什么样的内部工具用得上
典型场景是“境内团队 + 海外门户”:跨境供应链团队的 Retool 面板,运营每天把报关数据推到海外承运商门户,而提交页挂着 reCAPTCHA v2,只能有人守着一条条点。国内站点多用 GeeTest(极验)、网易易盾,reCAPTCHA 与 Turnstile 主要在海外站点——这类团队最容易撞上。CaptchaAI 支持 GeeTest v3,极验 v4 还要等官方支持。
步骤 1:把 CaptchaAI 配成 REST API 资源
进入 Resources → Create New → REST API,填三项:
| 配置项 | 填写值 |
|---|---|
| Name | CaptchaAI |
| Base URL | https://ocr.captchaai.com |
| Authentication | 留空,API Key 走查询参数 |
保存后即可在查询里选用。
步骤 2:提交查询 submitCaptcha
新建查询 submitCaptcha,资源选 CaptchaAI,GET,URL Path 填 /in.php。参数五个:
| 参数名 | 填写值 |
|---|---|
key |
{{secretsStore.CAPTCHAAI_API_KEY}} |
method |
userrecaptcha |
googlekey |
{{sitekeyInput.value}} |
pageurl |
{{pageurlInput.value}} |
json |
1 |
API Key 放进 Secrets Store(Settings → Secrets)再引用,别硬编码。json 必须带,否则接口返回纯文本,data 会是字符串。
Transformer(可选):
// 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
同样挂 CaptchaAI 资源,GET,URL Path 换成 /res.php,参数改成按任务 ID 查:
key:{{secretsStore.CAPTCHAAI_API_KEY}}action:getid:{{submitCaptcha.data.request}}json:1
Transformer:
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 这个 JavaScript 查询:
// 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();
三个数字是配套的:首轮等 15 秒,之后每 5 秒一次,最多 20 次,上限约 115 秒,卡在 Retool 对 JS 查询的 120 秒上限内。
步骤 5:界面只要五个组件
| 组件 | 作用与绑定 |
|---|---|
Text Input sitekeyInput / pageurlInput |
接收 sitekey 与页面 URL |
Button solveButton |
标签“开始识别”,绑定 solveCaptcha.trigger() |
| Loading Indicator | 可见条件 {{ solveCaptcha.isFetching }} |
Text Area tokenOutput |
只读,取 solveCaptcha.data?.token |
| Status Badge | 按 {{ solveCaptcha.data?.status }} 显示状态 |
加载指示器别省:轮询期间界面静默一分多钟,没有反馈,运营会以为卡死而反复点击。
步骤 6:把 token 交给下游请求
再建查询 submitForm,资源指向目标 API,POST,Body 带上 g-recaptcha-response: {{solveCaptcha.data.token}}。绑到“提交表单”按钮,启用条件设成 {{ solveCaptcha.data?.status === 'solved' }}。token 一次性且有有效期,尽快提交。
常见报错与处理
| 现象 | 原因 | 处理方式 |
|---|---|---|
ERROR_WRONG_USER_KEY |
Key 填错或不存在 | 到 Settings → Secrets 核对 |
| 返回纯文本而非 JSON | 少了 json=1 |
参数里补上 json: 1 |
| 轮询跑满仍 timeout | 识别耗时偏长 | 次数加到 30 或缩短间隔 |
submitCaptcha.data 为 undefined |
提交没跑过 | 循环里先触发提交 |
| JS 查询被中断 | 撞上 120 秒上限 | 保持 20 次 × 5 秒,或改用 Workflows |
| token 被目标站拒绝 | sitekey 或 pageurl 填错 | 核对取值页面 |
套餐怎么选:算并发,不算次数
CaptchaAI 按并发线程计费,不按次数:一个线程就是一个在处理的验证码,完成后立刻释放,套餐内次数不设上限。
| 套餐 | 价格 | 线程数 | 适合的规模 |
|---|---|---|---|
| BASIC | $15/月 | 5 | 单个面板,几个人用 |
| STANDARD | $30/月 | 15 | 多个内部应用共用 |
| ADVANCE | $90/月 | 50 | 批量提交几十条 |
要问的是“同时有几个请求在飞”,不是“一天识别多少次”:五个运营各点一次,峰值也就 5 个线程。价格按美元计价。
常见问题
轮询一直返回 CAPCHA_NOT_READY 直到超时,怎么排查?
先确认 sitekey 与 pageurl 取自同一页面,对不上任务会长期挂在队列里。再看提交返回的 status 是否为 1,不为 1 说明任务没建上。都正常就把次数提到 30 再观察。
120 秒不够用时,该改成 Retool Workflows 吗?
批量或耗时波动大的场景值得改:提交与取结果拆成两个节点,用循环控制间隔,不受执行上限约束。代价是延迟更高;交互式面板留在 JS 查询更顺手。
hCaptcha 和 GeeTest v4 能不能走同一套流程?
都不支持,GeeTest v4 的官方口径是即将支持、尚未上线。可套用本文流程的类型:reCAPTCHA v2 / v3(含 Enterprise)、Cloudflare Turnstile、GeeTest v3、图片/OCR 与九宫格验证码;CaptchaFox、Friendly Captcha、Lemin 为测试版。
换成 Turnstile 或图片验证码要改哪里?
只改提交查询的 method 与对应参数,轮询、循环和界面都不用动。回填时换字段名:Turnstile 用 cf-turnstile-response。
相关文章
下一步
先配好资源和两个查询,拿已知 sitekey 的测试页跑通,再接业务表单——领取 CaptchaAI API Key。
延伸阅读: