Developer documentation

Migrating from Friendly Captcha, reCAPTCHA or hCaptcha

Switching to CDPCaptcha takes two steps: replace the script, then point your server-side verification at our endpoint.
A compatibility mode mounts the widget on the element classes of the old service, so the HTML can stay as it is.

1. Create a sitekey and an API key

Sign up, create a sitekey for the website and an API key for the server.
Both are in your account.

2. Replace the script

Remove the old script tag(s) and add ours with data-compat set to the service you are leaving.
The widget then also mounts on the old element class and names the hidden field like the old service did, so form handlers that read that field keep working until you rename it.

From Friendly Captcha

HTML
<!-- remove -->\n<script type="module" src="…/site.min.js" async defer></script>\n<script nomodule src="…/site.compat.min.js" async defer></script>\n\n<!-- add -->\n<link rel="stylesheet" href="https://cdpcaptcha.com/core/assets/css/cdp-captcha.css">\n<script src="https://cdpcaptcha.com/core/assets/js/cdp-captcha.js" data-compat="frc" defer></script>\n\n<!-- keep or rename; both work -->\n<div class="frc-captcha" data-sitekey="YOUR_CDPCAPTCHA_SITEKEY"></div>\n<div class="cdp-captcha" data-sitekey="YOUR_CDPCAPTCHA_SITEKEY"></div>

Attribute mapping: data-sitekey, data-start (auto / focus / none), data-theme, lang and data-form-field-name have the same names and values.
Events: frc:widget.complete becomes cdpcaptcha:widget.complete (same for error, expire, reset, statechange);
event.detail.response is the token in both.
Server side: the siteverify request shape is the same (response, optional sitekey, X-API-Key header);
read success and, on failure, error.code.

From reCAPTCHA v2

HTML
<!-- remove -->\n<script src="https://www.google.com/recaptcha/api.js" async defer></script>\n\n<!-- add -->\n<link rel="stylesheet" href="https://cdpcaptcha.com/core/assets/css/cdp-captcha.css">\n<script src="https://cdpcaptcha.com/core/assets/js/cdp-captcha.js" data-compat="recaptcha" defer></script>\n\n<!-- the element can stay; the hidden field is named g-recaptcha-response -->\n<div class="g-recaptcha" data-sitekey="YOUR_CDPCAPTCHA_SITEKEY"></div>

On the server replace the call to siteverify at google.com with ours: send the field as response and your API key in the X-API-Key header instead of the secret parameter.
Read success.
data-size, data-callback and the grecaptcha JavaScript object have no equivalent;
use our events instead.
Invisible reCAPTCHA corresponds to data-start="auto".

From hCaptcha

HTML
<!-- remove -->\n<script src="https://js.hcaptcha.com/1/api.js" async defer></script>\n\n<!-- add -->\n<link rel="stylesheet" href="https://cdpcaptcha.com/core/assets/css/cdp-captcha.css">\n<script src="https://cdpcaptcha.com/core/assets/js/cdp-captcha.js" data-compat="hcaptcha" defer></script>\n\n<div class="h-captcha" data-sitekey="YOUR_CDPCAPTCHA_SITEKEY"></div>

The hidden field is named h-captcha-response in compatibility mode.
Replace the server call to hcaptcha.com/siteverify with ours as described above.

3. Switch the server-side check

HTTP
# before (any of the three services)
POST https://<old-service>/siteverify  secret=…  response=…

# after
POST https://cdpcaptcha.com/api/v1/siteverify
X-API-Key: ck_YOUR_API_KEY
response=…  sitekey=YOUR_CDPCAPTCHA_SITEKEY

4. Clean up

Once everything works, rename the element class to cdp-captcha, drop data-compat, and read the field cdp-captcha-solution.
Remove the old service from your CSP and privacy notice.

Comparison

TopicCDPCaptchaFriendly Captcha v2reCAPTCHA v2hCaptcha
Visitor tasknone (proof of work)none (proof of work)picture puzzlespicture puzzles
Cookies / trackingnonenoneGoogle cookiesyes
Hostingself-hosted or CTPFSaaS (EU option)GoogleSaaS
Element classcdp-captchafrc-captchag-recaptchah-captcha
Hidden fieldcdp-captcha-solutionfrc-captcha-responseg-recaptcha-responseh-captcha-response
Server authX-API-KeyX-API-Keysecretsecret