Skip to main content

Migration from Cloudflare Turnstile

This guide helps you migrate from Cloudflare Turnstile to MTCaptcha by swapping the client widget and replacing Turnstile’s siteverify flow with MTCaptcha CheckToken.

Why migrate from Cloudflare Turnstile​

  • Privacy and GDPR alignment: MTCaptcha documents privacy-aware handling suitable for EU-facing properties. See Privacy GDPR Compliance.
  • WCAG 2.1 AAA accessibility: Align with accessibility-oriented CAPTCHA UX and documentation. See Accessibility Compliance.
  • Global reliability, including China: MTCaptcha is delivered with mainland China in mind. See Works in China.

Migration at a glance​

Cloudflare TurnstileMTCaptcha
Client scripthttps://challenges.cloudflare.com/turnstile/v0/api.jshttps://service.mtcaptcha.com/mtcv1/client/mtcaptcha.min.js
Widget class.cf-turnstile (container <div class="cf-turnstile" data-sitekey="…"></div>).mtcaptcha (use <div class="mtcaptcha"></div>)
Token namecf-turnstile-response (hidden input / form field)mtcaptcha-verifiedtoken (hidden input name)
Backend APIPOST https://challenges.cloudflare.com/turnstile/v0/siteverify (secret + response)GET https://service.mtcaptcha.com/mtcv1/api/checktoken (privatekey + token)
Server-side verification only

Keep your MTCaptcha PrivateKey on the server. Browser code should only ever see the public SiteKey inside mtcaptchaConfig.

Step 1: Replace client-side script and widget​

<!-- Remove [Cloudflare Turnstile] -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY"></div>

<!-- Add [MTCaptcha] -->
<script>
var mtcaptchaConfig = { "sitekey": "YOUR_SITEKEY" };
</script>
<script src="https://service.mtcaptcha.com/mtcv1/client/mtcaptcha.min.js" async defer></script>
<div class="mtcaptcha"></div>
Load order

Set mtcaptchaConfig (with quoted "sitekey") before loading mtcaptcha.min.js.

If you used Turnstile appearance, callback, or refresh-expired options, port that behavior to MTCaptcha using JavaScript APIs and JS Callbacks.

Step 2: Update server-side verification​

Replace Turnstile siteverify with MTCaptcha CheckToken:

GET https://service.mtcaptcha.com/mtcv1/api/checktoken?privatekey=YOUR_PRIVATEKEY&token=VERIFIED_TOKEN

Pass the submitted mtcaptcha-verifiedtoken value as token.

Token lifetime and single use

Treat each token as short-lived. Validate soon after submission and avoid reusing the same token for multiple CheckToken calls unless you intentionally configure exceptions. See Validate Token (With Private Key).

Use https://service2.mtcaptcha.com/mtcv1/api/checktoken when you need fixed outbound IP allowlists (Validate Token).

Troubleshooting​

SymptomWhat to check
Blank widget / script 403Domain not allowed for your SiteKey in Admin Portal.
CSP errorsAllow https://service.mtcaptcha.com (and service2 if used).
Still reading cf-turnstile-responseUpdate form handling to mtcaptcha-verifiedtoken everywhere (tests included).
token-expiredUser delayed submit; regenerate token with a fresh solve.
Strict outbound firewallSwitch CheckToken host to service2.mtcaptcha.com per docs.

Further reading​

Post-Migration Checklist​

  • Removed Turnstile script, widget container, and siteverify integration.
  • mtcaptchaConfig with "sitekey": "YOUR_SITEKEY" precedes mtcaptcha.min.js.
  • Server verifies mtcaptcha-verifiedtoken via https://service.mtcaptcha.com/mtcv1/api/checktoken.
  • Ported Turnstile callbacks/refresh behavior to MTCaptcha where required.
  • Tested production + staging hostnames against Admin Portal settings.
  • CSP/network allows MTCaptcha assets and API.