---
type: how-to
title: 从 hCaptcha 迁移
summary: "用极少的改动把 hCaptcha 换成 Caputchin：同样的客户端组件加服务端核验的形态几乎一对一对应，这里是每一部分确切的改前改后。"
---

Caputchin 用和 hCaptcha 同样的两段式模型，即页面上一个产出令牌的组件、加一次确认它的服务端检查，所以迁移大多是一次机械的替换，而非一次重写。服务端交换尤其是镜像 hCaptcha 自己遵循的 `siteverify` 形态。这份指南给出每一部分的改前改后。

如果你还没创建一个 Caputchin 账户和站点密钥，就先去 [创建你的账户](/docs/getting-started/create-your-account)；你会需要一个给页面用的 **公钥**（`cpt_pub_...`）和一个给你后端用的 **密钥**（`cpt_sec_...`），和 hCaptcha 的 site key 与 secret key 同样的划分。

## 心智模型不变

```mermaid
flowchart LR
  A["你页面上的组件"] -->|令牌| B["你的表单 / 请求"]
  B -->|令牌| C["你的后端"]
  C -->|密钥 + 令牌| D["siteverify 端点"]
  D -->|成功？| C
```

你已经围绕 hCaptcha 建好的一切，即渲染一个组件、收集一个令牌、把它 POST 到你的服务器、在信任请求之前核验它，都留着。只有名字和端点变。

## 1. 换掉客户端代码片段

| | hCaptcha | Caputchin |
|---|---|---|
| 脚本 | `<script src="https://js.hcaptcha.com/1/api.js" async defer>` | `<script src="https://cdn.jsdelivr.net/npm/@caputchin/widget@3/dist/widget.js">` |
| 元素 | `<div class="h-captcha" data-sitekey="...">` | `<caputchin-widget sitekey="cpt_pub_...">` |
| 表单里的令牌字段 | `h-captcha-response`（自动注入） | `caputchin-token`（自动注入） |
| 在 JS 里读取令牌 | `hcaptcha.getResponse()` | [`pass` 事件](/docs/references/widget-methods-and-events) 的 `detail.token` |

和 hCaptcha 一样，Caputchin 组件 **自动注入一个隐藏的令牌字段** 进它所在的那个表单，所以如果你的表单本来就做一次普通 POST，你只改那个元素和你后端读取的字段名。完整的客户端设置见 [添加组件](/docs/getting-started/add-the-widget)，[CDN 对 npm 的选择](/docs/integration-guides/cdn)。

## 2. 换掉服务端核验

这是两者最接近的地方，请求和响应的形状几乎逐字段对齐。

| | hCaptcha | Caputchin |
|---|---|---|
| 端点 | `POST https://api.hcaptcha.com/siteverify` | `POST https://verify.caputchin.com/v1/siteverify` |
| 请求字段 | `secret`、`response` | `secret`、`response`（相同） |
| 响应 | `{ success, challenge_ts, hostname, "error-codes", score? }` | `{ success, challenge_ts, hostname, error-codes, score? }` |
| 信任规则 | 仅当 `success === true` 时行动 | 仅当 `success === true` 时行动（相同） |

一个格式注意：hCaptcha 的核验端点预期 `application/x-www-form-urlencoded`，而 Caputchin 的接受 JSON。如果你现有的代码发送的是表单编码的字段，就把请求体换成 JSON（`{"secret":"...","response":"..."}`），配 `Content-Type: application/json`。字段本身不变。完整的请求/响应参考在 [在你的后端核验一个令牌](/docs/integration-guides/verify-on-your-backend) 上；框架代码片段在 [后端示例](/docs/integration-guides/backend-examples)。

## 3. 丢掉分数，如果你用过 hCaptcha Enterprise

hCaptcha Enterprise 返回一个风险 `score`（其中 **更高的** 数意味着 **更多** 风险）并要你挑一个阈值。Caputchin **不** 那样工作：`success` 是一个权威的通过/失败，因为验证确实被通过了（一次 proof-of-work 检查，或一个 [在服务器上重新推导的游戏回合](/docs/understanding-caputchin/gaming-anti-cheat)），不是一个风险估计。

如果你的代码有 `if (data.score < 0.7)`，就把它换成 `if (data.success)`。Caputchin 的 `score` 字段毫不相干：它只为游戏回合存在，并且是 **游戏的** 分数（信息性的，给你自己的排行榜），绝非一个风险或机器人可能性，所以不要据它把守访问。（注意方向也是相反的，hCaptcha 的分数随风险上升；Caputchin 的随游戏表现上升。）

## 什么沿用过来，以及什么变得更好

- **你选 hCaptcha 时看中的那个隐私姿态，保留。** Caputchin 不采集 IP、User-Agent、指纹或行为遥测；这个协议无处安放一个访客标识符，所以没有可泄露或可出售的。见 [理念](/docs/understanding-caputchin/philosophy)。
- **一个可选的游戏。** 不再是一道图片选择挑战，你可以把验证变成一个你访客真心去玩的简短游戏，而它正是能扛住 AI 求解器的那一部分。见 [添加一个游戏](/docs/getting-started/add-a-game)。
- **一个严格的 CSP 保持严格。** Caputchin 在一个收紧的 Content-Security-Policy 下运行；你允许少数几个来源，而不是放松你的策略。见 [Caputchin 如何沙箱化游戏](/docs/understanding-caputchin/game-sandboxing#the-csp-you-set-on-your-own-page)。

## 坑

- **两个密钥，两个家。** 公钥（`cpt_pub_...`）放在页面上；密钥（`cpt_sec_...`）只留在服务端，恰好是那套 hCaptcha 纪律。不要把密钥交付给浏览器。
- **令牌是一次性的。** 和 hCaptcha 一样，一个令牌只核验一次。不要缓存或重放它。
- **改你后端读取的字段名。** 那个隐藏字段是 `caputchin-token`，不是 `h-captcha-response`，一个常见的一行之失。
- **请求体格式。** 把核验请求作为 JSON 发送，而非表单编码。

## 另见

- [添加组件](/docs/getting-started/add-the-widget)：完整的客户端设置。
- [在你的后端核验一个令牌](/docs/integration-guides/verify-on-your-backend)：那个权威的 `siteverify` 参考。
- [后端示例](/docs/integration-guides/backend-examples)：每种语言里的核验调用。
- [添加一个游戏](/docs/getting-started/add-a-game)：把验证变成一个游戏。
