Caputchin
Migration guides

Migrate from reCAPTCHA

Caputchin uses the same two-part model as reCAPTCHA, a widget on the page that produces a token, and a server-side check that confirms it, so migrating is mostly a mechanical swap, not a rewrite. The server exchange in particular mirrors reCAPTCHA's siteverify shape on purpose. This guide gives the before-and-after for each piece.

If you have not yet created a Caputchin account and site key, do create your account first; you will need a public key (cpt_pub_...) for the page and a secret (cpt_sec_...) for your backend, the same split as reCAPTCHA's site key and secret key.

The mental model is unchanged

Everything you already built around reCAPTCHA, render a widget, collect a token, POST it to your server, verify it before trusting the request, stays. Only the names and endpoints change.

1. Swap the client snippet

reCAPTCHA (v2 checkbox)Caputchin
Script<script src="https://www.google.com/recaptcha/api.js" async defer><script src="https://cdn.jsdelivr.net/npm/@caputchin/widget@3/dist/widget.js">
Element<div class="g-recaptcha" data-sitekey="..."><caputchin-widget sitekey="cpt_pub_...">
Token field in a formg-recaptcha-response (auto-injected)caputchin-token (auto-injected)
Reading the token in JSgrecaptcha.getResponse()the pass event detail.token

Like reCAPTCHA, the Caputchin widget auto-injects a hidden token field into the form it sits in, so if your form already did a normal POST, you only change the element and the field name your backend reads. See add the widget for the full client setup and the CDN vs npm choice.

2. Swap the server verify

This is where the two are closest, the request and response shapes line up almost field for field.

reCAPTCHACaputchin
EndpointPOST https://www.google.com/recaptcha/api/siteverifyPOST https://caputchin.com/api/v1/siteverify
Request fieldssecret, responsesecret, response (identical)
Response{ success, challenge_ts, hostname, "error-codes" }{ success, challenge_ts, hostname, error-codes, score? }
Trust ruleact only if success === trueact only if success === true (identical)

In most stacks the only change to your verification code is the URL and the secret value. The full request/response reference, including the error codes, is on verify a token on your backend; framework snippets are in backend examples.

3. Map the score, if you used reCAPTCHA v3

reCAPTCHA v3 returns a score (0.0 to 1.0) and asks you to pick a threshold, you are guessing how human a request looked. Caputchin does not work that way: success is an authoritative pass/fail, because the verification was actually cleared (a proof-of-work check, or a game round re-derived on the server), not a probability.

If your code had if (data.score >= 0.5), replace it with if (data.success). Caputchin's score field exists only for game rounds and is the game's score (informational, for your own leaderboards), never a bot-likelihood, so do not gate access on it.

What gets better in the move

  • No visitor data collection. reCAPTCHA profiles your visitors; Caputchin collects no IP, User-Agent, fingerprint, or behavioral telemetry, the protocol has nowhere to put a visitor identifier. See the philosophy.
  • One widget, not v2-vs-v3. There is no separate invisible/score product to choose between; one element covers the checkbox and the optional game.
  • An optional game. Instead of a grid-of-traffic-lights, you can turn verification into a short game your visitors actually play. See add a game.
  • A strict CSP stays strict. Caputchin runs under a tight Content-Security-Policy; you allow a few origins rather than loosen your policy. See how Caputchin sandboxes games.

Gotchas

  • Two keys, two homes. The public key (cpt_pub_...) goes on the page; the secret (cpt_sec_...) stays server-side only, exactly the reCAPTCHA discipline. Do not ship the secret to the browser.
  • The token is single-use. Like reCAPTCHA, a token verifies once. Do not cache or replay it.
  • Change the field name your backend reads. The hidden field is caputchin-token, not g-recaptcha-response, a common one-line miss.

See also

On this page