Skip to content

迁移指南 ​

从 reCAPTCHA / hCaptcha / Turnstile 迁移到 Capcat 只有两处改动:

  1. 前端:换 <script> 地址,把验证容器换成 <cap-widget>;
  2. 服务端:换 siteverify 的 URL、secret,以及读取的表单字段名。

siteverify 请求同时兼容 JSON 与表单编码(secret=…&response=…),原有的 reCAPTCHA / hCaptcha 客户端代码通常只改 URL 和 secret 就能用。

开始前先在控制台创建站点,拿到你的 site key 和 secret。

对照总览 ​

reCAPTCHA v2hCaptchaTurnstileCapcat
脚本地址www.google.com/recaptcha/api.jsjs.hcaptcha.com/1/api.jschallenges.cloudflare.com/turnstile/v0/api.jscapcat.ai/widget/cap.js
前端标签<div class="g-recaptcha"><div class="h-captcha"><div class="cf-turnstile"><cap-widget>
表单 token 字段g-recaptcha-responseh-captcha-responsecf-turnstile-responsecap-token
siteverify 地址www.google.com/recaptcha/api/siteverifyapi.hcaptcha.com/siteverifychallenges.cloudflare.com/turnstile/v0/siteverifyapi.capcat.ai/<site-key>/siteverify
通过判定success: truesuccess: truesuccess: truesuccess: true

从 reCAPTCHA 迁移 ​

前端 ​

html
<!-- 之前 -->
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<form action="/submit" method="POST">
  <div class="g-recaptcha" data-sitekey="<recaptcha-site-key>"></div>
  <button type="submit">提交</button>
</form>

<!-- 之后 -->
<script src="https://capcat.ai/widget/cap.js"></script>
<form action="/submit" method="POST">
  <cap-widget data-cap-api-endpoint="https://api.capcat.ai/<site-key>/"></cap-widget>
  <button type="submit">提交</button>
</form>

<cap-widget> 放在 <form> 内会自动注入隐藏的 cap-token 字段随表单提交,与 g-recaptcha-response 的机制一致;不需要 onload 回调或 grecaptcha.render()。

服务端 ​

把 siteverify 的 URL 换成 Capcat、secret 换成控制台生成的 secret、读取的字段从 g-recaptcha-response 换成 cap-token:

js
// 之前
const token = req.body["g-recaptcha-response"];
const r = await fetch("https://www.google.com/recaptcha/api/siteverify", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({ secret: RECAPTCHA_SECRET, response: token }),
});

// 之后 —— 表单编码原样可用,只改了 URL、secret 与字段名
const token = req.body["cap-token"];
const r = await fetch("https://api.capcat.ai/<site-key>/siteverify", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({ secret: CAPCAT_SECRET, response: token }),
});

const { success } = await r.json();

remoteip 等多余参数会被忽略,不必删除。

用的是 reCAPTCHA v3? ​

纯 Capcat 验证可以用通过 / 不通过直接替代 v3:工作量证明在浏览器后台静默完成,用户只需点一次复选框,没有图形拼图。若不启用客户自有 reCAPTCHA v3,把原来的 Google 阈值判断改为检查 success 即可;若仍需要 Google 分数,可开启可选的 BYOK reCAPTCHA v3 防线,鉴权后的 Capcat siteverify 会返回与 token 绑定的 score,详见服务端验证 API。

从 hCaptcha 迁移 ​

前端 ​

html
<!-- 之前 -->
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
<div class="h-captcha" data-sitekey="<hcaptcha-site-key>"></div>

<!-- 之后 -->
<script src="https://capcat.ai/widget/cap.js"></script>
<cap-widget data-cap-api-endpoint="https://api.capcat.ai/<site-key>/"></cap-widget>

服务端 ​

hCaptcha 的 siteverify 与 reCAPTCHA 同构:URL 换成 https://api.capcat.ai/<site-key>/siteverify,secret 换成 Capcat 的,token 字段从 h-captcha-response 换成 cap-token。表单编码与 JSON 都接受,sitekey / remoteip 参数忽略即可。

py
# 之前
requests.post("https://api.hcaptcha.com/siteverify",
    data={"secret": HCAPTCHA_SECRET, "response": request.form["h-captcha-response"]})

# 之后
requests.post("https://api.capcat.ai/<site-key>/siteverify",
    data={"secret": CAPCAT_SECRET, "response": request.form["cap-token"]})

从 Turnstile 迁移 ​

前端 ​

html
<!-- 之前 -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="<turnstile-site-key>"></div>

<!-- 之后 -->
<script src="https://capcat.ai/widget/cap.js"></script>
<cap-widget data-cap-api-endpoint="https://api.capcat.ai/<site-key>/"></cap-widget>

服务端 ​

Turnstile 的 siteverify 支持 JSON 与表单编码,Capcat 同样两者都支持——只改 URL、secret 与字段名(cf-turnstile-response → cap-token):

js
// 之前
const r = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ secret: TURNSTILE_SECRET, response: token }),
});

// 之后
const r = await fetch("https://api.capcat.ai/<site-key>/siteverify", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ secret: CAPCAT_SECRET, response: token }),
});

迁移注意事项 ​

  • token 一次性有效:siteverify 校验成功一次后立即失效,重放返回 success: false(与三家行为一致)。有效期 5 分钟(2026 年 11 月之前创建的站点为 20 分钟)。
  • remoteip 与 idempotency_key:字段名与 reCAPTCHA / hCaptcha / Turnstile 相同。随着你的站点逐步开放,Capcat 会把 remoteip 与解题的客户端比对,并对带相同 idempotency_key 的重试返回原结果,详见把 token 绑定到访客。
  • 默认兼容、风险信息按需开启:基础响应仍只要求检查 success。客户自有 reCAPTCHA v3 可增加其标准 score;若启用 Account Defense Score 模式且运行门禁已生效,还可增加 action 与带版本的 risk_* 字段。两种分数方向及缺失字段处理详见服务端验证 API。
  • 域名绑定:对应 reCAPTCHA / hCaptcha 的域名白名单,在控制台站点设置里配置「允许的域名」;绑定后其他来源的验证请求会被直接拒绝。
  • 内容安全策略(CSP):若站点启用了严格 CSP,需放行 capcat.ai(脚本与 wasm)和 api.capcat.ai(验证请求)。
  • SPA / 自定义流程:不用表单提交时,监听组件的 solve 事件拿 token,详见前端组件。

迁移过程中新旧验证可以并行:前端逐页替换,服务端按 token 字段名区分走哪家校验,全部切完后再移除旧依赖。

基于 Cap(Apache 2.0)构建