Skip to content

迁移指南

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

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

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

开始前先在控制台创建站点,拿到你的 site keysecret

对照总览

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?

v3 的「无感评分」没有直接对应物——Capcat 不给用户打分,验证结果只有通过 / 不通过。但 v3 的典型场景(表单防刷、接口防滥用)可以直接用 Capcat 替代:工作量证明在浏览器后台静默完成,用户只需点一次复选框,没有图形拼图。服务端不再有 scoreaction 字段,把阈值判断改为检查 success 即可。

从 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-responsecap-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(与三家行为一致)。默认有效期 20 分钟。
  • 没有评分与动作:响应里没有 score / action / hostname 字段,通过判定只看 success
  • 域名绑定:对应 reCAPTCHA / hCaptcha 的域名白名单,在控制台站点设置里配置「允许的域名」;绑定后其他来源的验证请求会被直接拒绝。
  • 内容安全策略(CSP):若站点启用了严格 CSP,需放行 capcat.ai(脚本与 wasm)和 api.capcat.ai(验证请求)。
  • SPA / 自定义流程:不用表单提交时,监听组件的 solve 事件拿 token,详见前端组件

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

基于 Cap(Apache 2.0)构建