What this covers
Turnstile has two halves and you need both. A widget on the page gives the visitor a one-time token. Your server then asks Cloudflare whether that token is genuine before it accepts the form. The widget on its own stops nothing, because a bot can post to your form without ever loading the page.
Before you start
You need a Cloudflare account (free) and the domain your form is served from. Your domain does not have to use Cloudflare for DNS. Each key only works on the hostnames you list for it, so a key created for one site will not work on another.
How to do it
- Sign in at dash.cloudflare.com, open Turnstile and choose Add widget. Give it a name, add your domain as a hostname, and leave the mode on Managed. Adding example.com also covers www.example.com and other subdomains.
- Copy the two values Cloudflare shows you. The site key is public and goes in your page. The secret key is private and stays on your server.
- Load the Turnstile script on the page that has the form: <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
- Put the widget inside the form, above the submit button: <div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>. When the visitor submits, the form carries an extra field called cf-turnstile-response.
- In the code that receives the form, send a POST to https://challenges.cloudflare.com/turnstile/v0/siteverify with two fields: secret (your secret key) and response (the value of cf-turnstile-response). Accept the submission only if the reply says "success": true. A token works once and expires after five minutes.
- On App Hosting, save the secret as an environment variable such as TURNSTILE_SECRET_KEY: open the app service, go to Environment Variables, add it, and redeploy. Do not commit it to your repository or put it in front-end code.
- On Managed WordPress with CM Cloud, we install it for you. Open your WordPress service in the portal, find Spam protection, paste the site key and the secret key, and choose Install and turn on. Comments, registration and password reset are protected. Tick the login option only if the widget was created for exactly that domain; if the login page ever stops working, turn spam protection off from the same place. On a WordPress hosted elsewhere, install the Simple Cloudflare Turnstile plugin yourself and paste both keys into its settings.
- A website built with AI Launch needs no key of its own. Open the AI studio in the portal, scroll to Enquiries from your website, and choose Turn on spam protection. Visitors then pass a quick check on our page before their message is sent, and your site does not need republishing.
- Test it: submit the form normally and check it goes through, then post to your form's address without the token and check your server refuses it.
What our team checks
If the widget shows an error about the domain, the hostname you are visiting is not on the widget's list in Cloudflare. If every submission is refused, check that the secret key on the server belongs to the same widget as the site key on the page.
Next step
A static site has no server to do the check, so the widget alone will not protect it. Point the form at a small backend you control, or move the form into an app that has one.