caputchin
All docs
View raw .md

Migrate from reCAPTCHA

Caputchin's /siteverify is intentionally shape-compatible with Google's reCAPTCHA verify endpoint. The browser surface differs (custom element instead of a script + global), but your server-side code mostly keeps working as-is.

This guide assumes you already have Caputchin site keys. See quickstart if not.

Field mapping

Browser HTML

reCAPTCHA Caputchin
<script src="https://www.google.com/recaptcha/api.js"></script> <script src="https://cdn.jsdelivr.net/npm/@caputchin/widget@1/dist/widget.js"></script>
<div class="g-recaptcha" data-sitekey="..."></div> <caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
Form field g-recaptcha-response Form field caputchin-token
data-callback="onSubmit" addEventListener("complete", onSubmit)

For invisible reCAPTCHA v2, the equivalent is the Caputchin invisible default — just omit the game attribute. For v3 (no challenge UI), use the same invisible default.

Backend /siteverify

reCAPTCHA request body Caputchin request body
secret=YOUR_SECRET secret: "cpt_sec_..."
response=USER_TOKEN response: "<caputchin-token>"
remoteip=USER_IP (optional) not used — Caputchin does not collect IPs
reCAPTCHA response Caputchin response
success: true | false success: true | false (same)
error-codes: [] error-codes: [] (same)
score: 0.0–1.0 (v3) not provided — Caputchin treats game score as metadata, not a trust signal
action: "..." (v3) not provided — see principles below
challenge_ts not provided
hostname not provided

The shape compatibility means a server using recaptcha.verify(token) can usually be redirected to Caputchin by changing only the URL and only the secret.

Step-by-step swap

1. Replace the script tag

Remove the reCAPTCHA <script> and replace <div class="g-recaptcha"> with <caputchin-widget>. If your form uses g-recaptcha-response, rename the field accessor in your backend to caputchin-token.

2. Update the secret

Replace your reCAPTCHA secret in your environment with the Caputchin secret (cpt_sec_...). Same env var name is fine.

3. Update the verify URL

Change the verify endpoint:

-const VERIFY_URL = "https://www.google.com/recaptcha/api/siteverify";
+const VERIFY_URL = "https://api.caputchin.com/api/v1/siteverify";

4. Drop reCAPTCHA-specific assertions

If your verifier reads score, action, hostname, or challenge_ts, remove those checks. Caputchin gives you success + error-codes and that is the entire trust signal. The wrapped token also carries game_id, score, and duration_ms, but those are client-claimed metadata, not security signals — do not gate access on them.

5. Test in staging

Submit the form with a real challenge and inspect the verdict. The shape should be familiar:

{
  "success": true,
  "platform": { "game_id": "bubble-pop", "score": 0.847, "duration_ms": 4200 }
}

If anything is wrong, the troubleshooting guide maps every error code.

Principles {#principles}

Two things are intentionally different from reCAPTCHA:

Difference Why
No risk score Caputchin makes no behavioral risk claims. Cap's proof-of-work is the entire humanity signal.
No IP / user-agent / fingerprint collection Caputchin is structurally private — there is no remoteip field because the platform does not store user IPs.

The full positioning is in privacy.

Rollback plan

If you need to roll back, keep both the old and new scripts side-by-side for one deploy. The form field name is the only meaningful collision — rename one of them temporarily, then swap when you are confident.