HostleloBlog
SavedSearch
Visit Hostlelo

Stop WordPress Spam With Cloudflare Turnstile (No CAPTCHA)

Add Cloudflare's free, puzzle-free Turnstile check to WordPress login, comments and contact forms, then prove it refuses posts that carry no valid token.

The short answer

Cloudflare Turnstile is a free bot check that replaces CAPTCHA puzzles with quiet browser checks. On WordPress you create a widget in the Turnstile section of the Cloudflare dashboard, paste its sitekey and secret key into a plugin such as Simple CAPTCHA with Cloudflare Turnstile, and choose which forms to protect. It only works when your server validates each token with Cloudflare's siteverify endpoint, so test it by sending a tokenless post and confirming it is refused.

A website form is protected by a purple shield while unwanted messages stay outside and a verified green message passes through.
Reading options

On this page

You can stop most bot spam on WordPress login, comment and contact forms with Cloudflare Turnstile, a free bot check that asks your visitors to solve no puzzle at all. You create a widget in Cloudflare, paste two keys into a WordPress plugin, and pick the forms to protect. The part most people skip is the test that proves your server really rejects a post with no valid token, and that is where this guide spends real time.

Here is the fact that surprises people: Cloudflare's own docs say that if your server never checks the token, Turnstile Analytics simply shows zeros. The widget can look perfect on the page while a bot posts straight to your form and nothing stops it.

By the end you will have Turnstile running on your login, comments and contact forms, and you will have sent a fake post to your own site and watched it get refused.

What Turnstile actually is

Turnstile is what Cloudflare calls its "smart CAPTCHA alternative". A CAPTCHA is the old "click all the traffic lights" test. Turnstile skips the puzzle and runs quiet checks in the visitor's browser instead.

Think of it like a concert wristband. The person at the door (the widget in the browser) checks you and snaps a wristband on. The bouncer inside (your server) still looks at every wrist before letting anyone near the stage. A wristband nobody checks is decoration.

In tech terms, the widget hands the browser a token, which is a short one-time code. Your form sends that token along with the comment or login. Your server then asks Cloudflare, "Is this token real?" before it accepts anything.

Cloudflare offers a few widget modes. Managed is the recommended one: Cloudflare decides whether to show a checkbox based on how risky the visitor looks. Non-interactive never asks the visitor to do anything, and Invisible hides the widget completely.

Quick tip: start with Managed. Real people almost never see more than a checkbox, and you can change the mode later without touching WordPress.

Why this matters: a token is only good for 300 seconds (5 minutes) and can only be checked once. A bot cannot grab one token and reuse it on a thousand spam comments.

Before you start

Run through this list before you touch anything. It takes two minutes and saves an awkward afternoon.

  • Admin access to your WordPress dashboard.
  • A Cloudflare account (the free one is fine).
  • A fresh backup of your files and database, taken from your hosting panel or your backup plugin, and stored somewhere other than the server.
  • A staging copy of the site if you have one, so you can test there first (recommended, not required).
  • About 30 minutes.
  • A second browser, or a private window, logged in as an admin and left open the whole time.

The risk is low, but a broken login form is possible. If the widget fails to load on wp-login.php, you could lock yourself out. That second logged-in session is your way back in, because you can switch the plugin off from inside it.

Heads up: if you have SSH access, also make sure WP-CLI works on your server. It gives you a second escape route that does not need a browser at all. I cover the exact command in the troubleshooting section.

On the Cloudflare side, at the time of writing (3 Nov 2026) the Turnstile free plan costs nothing, allows up to 20 widgets per account and 10 hostnames per widget, includes all widget types, has unlimited challenges, and keeps analytics for 7 days. Removing the Cloudflare branding from the widget is an Enterprise feature.

Set up Turnstile on WordPress with a plugin

The simplest route uses a plugin called Simple CAPTCHA with Cloudflare Turnstile. It is a third-party plugin made by Elliot Sowersby / RelyWP, not by Cloudflare, so treat it like any other plugin you install: keep it updated and read its changelog.

At the time of writing (3 Nov 2026), the plugin is on version 1.44.5 with 200,000+ active installs, it is tested up to WordPress 7.1.4, and it needs WordPress 4.7 or newer. Its latest changelog entry is dated 31 Oct 2026 and includes two security fixes, which is a good reminder of why updates matter.

Step 1: Create a Turnstile widget

A widget is Cloudflare's name for one Turnstile setup. It holds your settings and gives you two keys.

  1. Log in to Cloudflare and go to the Turnstile page in the dashboard.
  2. Click Add widget.
  3. Give it a Widget name you will recognise later, such as "example.com forms".
  4. Under Hostname management, add the domain the forms live on, for example example.com.
  5. Set Widget mode to Managed.
  6. Leave Pre-clearance support off; it is meant for single page apps.
  7. Click Create.

You should now see two keys. The sitekey is public and goes into your page. The secret key is private and only your server should ever see it.

Heads up: copy the secret key straight into a password manager. Do not paste it into a support chat, a screenshot or a public ticket.

Quick tip: if you have a staging copy on a different domain, add that hostname to the same widget too. It counts toward the 10 hostnames, and it saves you a "domain not authorized" error later.

Step 2: Install and activate the plugin

You can install it from the Plugins screen in your dashboard by searching for "Simple CAPTCHA with Cloudflare Turnstile". The plugin's own instructions describe the manual way: upload the simple-cloudflare-turnstile folder to /wp-content/plugins/, then activate it from the Plugins menu.

If you prefer the command line, this WP-CLI command installs the plugin from WordPress.org and activates it in one go.

wp plugin install simple-cloudflare-turnstile --activate

You should see WP-CLI report that the plugin was installed and activated, followed by a Success: line.

Step 3: Paste your keys

  1. Go to Settings > Cloudflare Turnstile.
  2. Paste your sitekey into Site Key.
  3. Paste your secret key into Secret Key.
  4. Check that neither field picked up a space at the start or end.

Do not save yet. Picking the forms comes first, so you only save once.

Step 4: Choose which forms to protect

The plugin lists the forms it can protect. For core WordPress that means login, registration, password reset and comments.

It also covers WooCommerce login, registration and checkout, plus popular form plugins such as Contact Form 7, WPForms, Fluent Forms, Gravity Forms and Elementor Pro Forms, among others.

My advice is to turn on login and comments first, plus the one contact form you use most. Add the rest once you have seen those work.

Why this matters: every form you leave unprotected is the one bots will find. If you run open registration, protect that form too, and read how to check your registration default role so a bot that does get through cannot sign up as anything more than a subscriber.

Step 5: Save and run the API test

  1. Click Save Changes.
  2. Click TEST API RESPONSE and complete the quick widget test.

The plugin's own docs say this test is required. If you skip it, the challenge may not appear on your forms at all.

After the test passes, open your login page in a private window. You should see the Turnstile widget sitting above the login button.

Made-up example: the comment flood

Made-up example: Sara runs a small recipe blog. Every morning she deletes about 40 spam comments (an invented number for this story). She installs the plugin, ticks Comments, saves and runs the test.

The widget appears under her comment box and she relaxes. A week later her inbox is still full of junk. The cause: the bots had moved to her Contact Form 7 form, which she never ticked in the plugin settings.

She ticks it, saves, runs the test again, and then posts a tokenless test to each form. The morning cleanup stops. The lesson she took away: the widget showing up proves nothing; a refused bot post proves everything. That is exactly the test we will run below.

Variants

The plugin route

This is the route above, and it is the one I recommend for most sites. The plugin handles both halves: it shows the widget and it checks the token with Cloudflare on your server.

The manual route with your own code

You can wire Turnstile into WordPress yourself by printing the widget script and calling the siteverify endpoint from PHP. I am not including code for that here, because a hand-rolled version needs to hook into each form's validation correctly, and a small mistake leaves the form open while the widget still looks fine.

If a developer builds it for you, ask them to show you the server-side check, and run the curl tests below against their work.

Confirm the plugin is active with WP-CLI

This command shows the status, version and details of the Turnstile plugin.

wp plugin status simple-cloudflare-turnstile

You should see a block of details that includes a line reading Status: Active. If it says Inactive, activate it again from the Plugins screen.

How to check it worked

This is the bit that closes the loop from the top of the post. The widget being visible is half the job. Now you prove the server half.

Check 1: Your secret key talks to Cloudflare

This curl command sends a fake token to Cloudflare's siteverify endpoint using your real secret key. Replace YOUR_SECRET_KEY with the secret key from Step 1, and run it from your own computer or the server.

curl -s -X POST https://challenges.cloudflare.com/turnstile/v0/siteverify -d "secret=YOUR_SECRET_KEY" -d "response=fake-token-for-testing"

You should get back JSON where success is false and error-codes lists invalid-input-response. Cloudflare's docs show a failure in this shape.

{
  "success": false,
  "error-codes": ["invalid-input-response"]
}

That result is good news. It means Cloudflare recognised your secret key and refused the fake token. If you see invalid-input-secret instead, your secret key is wrong, and the troubleshooting section tells you what to do.

Siteverify is the address your server calls to check a token. It takes two required fields, secret and response, plus optional remoteip (the visitor's IP address) and idempotency_key (a code that makes retries safe). A real success reply includes success, challenge_ts, hostname and error-codes.

Quick tip: run this only on a machine you trust, and never paste the full command with your real key into a ticket or chat. Your shell may also save it in its history file, so clear that entry afterwards.

Check 2: A comment without a token gets refused

Do this on staging if you can, because if protection is off it will create a real test comment. This curl command posts a comment straight to WordPress with no Turnstile token, the way a basic spam bot would. Change example.com to your site and comment_post_ID=1 to the ID of a post with comments open.

curl -s -X POST https://example.com/wp-comments-post.php -d "comment_post_ID=1" -d "author=Test Bot" -d "email=bot@example.com" -d "comment=Tokenless test comment, please delete"

You should get an error page back mentioning the Turnstile check, and no new comment should appear under Comments in your dashboard. Check the pending queue too. The exact wording depends on the plugin version, so look for a refusal rather than a specific sentence.

If the comment does show up, protection on comments is not working. Go back to Step 4, make sure Comments is ticked, save, and run TEST API RESPONSE again.

Check 3: A login with a wrong password

Open your login page in a private window. Complete the widget, enter a real username and a wrong password, and submit.

You should see WordPress's normal wrong password error. Then log in properly with the right password to confirm real people still get in.

Why this matters: this proves the widget does not break normal logins. Keep your second admin session open until this test passes.

Check 4: Your contact form

Send yourself a message through your main contact form in a private window. It should arrive as usual, and the widget should be visible on the form.

Check 5: The Turnstile analytics

Go back to the Turnstile page in Cloudflare and open your widget. After your tests and a little real traffic, you should see numbers there rather than zeros.

Remember the warning from the top: zeros mean your server is not validating tokens. Numbers mean the bouncer is checking wristbands. On the free plan, analytics go back 7 days.

Troubleshooting

Problem: invalid-input-secret in the curl test

Symptom: Check 1 returns success as false with invalid-input-secret in error-codes.

Likely cause: the secret key is wrong, has a stray space, or is the sitekey pasted in the wrong field. Cloudflare describes this error as a secret key that is invalid or expired.

Fix: copy the secret key again from your widget in Cloudflare, paste it into Secret Key in Settings > Cloudflare Turnstile, save, and run TEST API RESPONSE again.

Problem: missing-input-secret

Symptom: siteverify returns missing-input-secret.

Likely cause: the request reached Cloudflare without any secret at all. In the curl test this usually means a quoting mistake in the -d "secret=..." part.

Fix: check the command carefully. In the plugin, it means the Secret Key field is empty, so paste the key and save.

Problem: timeout-or-duplicate

Symptom: a real visitor's form fails, and your logs or a developer's debug output show timeout-or-duplicate.

Likely cause: the token was already checked once, or more than 300 seconds passed before the form was sent. A visitor who leaves a long contact form open while making tea can hit this.

Fix: the visitor should reload the page and submit again. If it happens a lot, ask your developer whether a cache or a form plugin is submitting the same token twice.

Problem: invalid-input-response

Symptom: forms fail for real visitors and the error is invalid-input-response.

Likely cause: Cloudflare says the token is invalid, malformed or expired. If you use full page caching, an old cached copy of the form page is one thing worth ruling out.

Fix: ask the visitor to retry the challenge. Exclude your login and form pages from full page caching and test again in a private window.

Problem: the widget shows "Domain not authorized" (error 110200)

Symptom: the widget appears with an error instead of the usual box, and Cloudflare's client error code is 110200.

Likely cause: the hostname the page is on is not listed in the widget's Hostname management. This happens a lot on staging sites and www versus non-www setups.

Fix: add the exact hostname in Hostname management on your widget, then reload the page.

Problem: "Invalid sitekey" (error 110100) or "Sitekey not found" (error 110110)

Symptom: the widget fails to load and shows one of those client error codes.

Likely cause: the sitekey has a typo, or it belongs to a widget you deleted.

Fix: copy the sitekey again from your widget in Cloudflare, paste it into Site Key, save, and run TEST API RESPONSE.

Problem: you are locked out of wp-admin

Symptom: the login form will not accept your login, or the submit button will not work, even with the right password.

Likely cause: the widget is not loading or the keys do not match, so every login fails the check.

Fix: use your second admin session to go to Plugins and deactivate the Turnstile plugin. If you have no session open but you do have SSH access, this WP-CLI command switches the plugin off.

wp plugin deactivate simple-cloudflare-turnstile

You should see Plugin 'simple-cloudflare-turnstile' deactivated. followed by a Success: line. Log in normally, fix the keys or hostname, then reactivate the plugin. If you have neither a session nor SSH, ask your host to deactivate the plugin for you.

Pro tips and security notes

Do not rely on Turnstile alone

Turnstile is one layer. It stops a lot of automated junk, but it does not patch an outdated plugin, fix a weak password or close an old login door.

Keep WordPress core, your theme and every plugin updated, including this one. After a big round of updates, check for new PHP warnings the careful way with our guide to reading the debug log safely after an update.

Close the side doors

xmlrpc.php is a separate way for apps to talk to WordPress, and it never shows your login page, so the Turnstile widget is not there to help. If you do not use it, read how to disable XML-RPC safely.

For login floods, pair Turnstile with a rate limit at the edge. Our walkthrough on using Cloudflare's free rate limiting for wp-login shows how to slow down repeated attempts before they ever reach WordPress.

Use Cloudflare's test keys on staging

Cloudflare publishes test keys for development. The test sitekey 1x00000000000000000000AA always passes, and 2x00000000000000000000AB always fails, both with a visible widget.

The test secret key 1x0000000000000000000000000000000AA always validates, and 2x0000000000000000000000000000000AA always fails. Cloudflare notes that production secret keys reject dummy tokens, so never leave test keys on a live site: they would let everything through or block everyone.

Treat the secret key like a password

Anyone with your secret key can validate tokens as your site. If you think it has leaked, rotate it in the Turnstile section of the Cloudflare dashboard (Cloudflare has a guide called "Rotate secret key"), then paste the new one into the plugin and run TEST API RESPONSE again.

The one message worth forwarding

If someone else looks after your site, copy this and send it to them.

Hi, could you add Cloudflare Turnstile to our WordPress site on login, comments and the main contact form? I am happy with the free plugin "Simple CAPTCHA with Cloudflare Turnstile" (third-party, by RelyWP) or your own setup. Two things matter to me: please confirm the server checks each token with Cloudflare's siteverify endpoint, and show me that a comment posted with curl and no token is refused. Please also check that Turnstile Analytics shows real numbers, not zeros, after a day. Keep a second admin session open while testing so nobody gets locked out. Thanks!

A Turnstile widget only protects you once your server checks the token, so test with a tokenless post and trust the refusal, not the checkbox.

Reader questions

Is Cloudflare Turnstile really free?

Yes. At the time of writing (3 Nov 2026) Cloudflare lists the Turnstile free plan at no cost with unlimited challenges, so a small WordPress site does not need a paid plan to use it.

Does the Turnstile plugin work on WordPress Multisite or with two-factor login plugins?

The plugin's WordPress.org page says it works with WordPress Multisite and with most two-factor authentication plugins. Test your exact login setup on staging before enabling it on a live network.

I see a 401 error in the browser console after adding Turnstile. Is something broken?

The plugin's FAQ says this 401 console error can be safely ignored. It relates to a Private Access Token request that some browsers do not support.

Which other form plugins can Simple CAPTCHA with Cloudflare Turnstile protect?

Besides the common ones, its WordPress.org page lists Formidable Forms, Forminator, Jetpack Forms, Kadence Forms, SureForms, MailPoet, Mailchimp for WordPress, BuddyPress and bbPress, among others.

Which WooCommerce forms does the plugin cover?

The plugin lists WooCommerce Checkout, Pay For Order, Account Details, Login, Registration and Password Reset. Test a full checkout on staging after enabling it.

Where do I get help with the plugin?

Support is community-based through the WordPress.org support forums for the plugin, and the developer does not promise to answer every ticket.

How do I report a security problem in the Turnstile plugin?

The plugin's WordPress.org page asks people to submit security reports through the Patchstack Vulnerability Disclosure Program rather than the public forums.

Sources & further reading

  1. Cloudflare Turnstile overview
  2. Cloudflare Turnstile: Get started
  3. Cloudflare Turnstile: Server-side validation
  4. Cloudflare Turnstile: Create a widget in the dashboard
  5. Cloudflare Turnstile: Plans
  6. Cloudflare Turnstile: Testing
  7. Cloudflare Turnstile: Client-side error codes
  8. Simple CAPTCHA with Cloudflare Turnstile on WordPress.org
  9. WP-CLI: wp plugin status
  10. WordPress reference: wp_handle_comment_submission()

What changed

Added an original cover illustration, descriptive alt text and matching social image. Article text and publication timing are unchanged.

Originally published . About our editorial updates.

Your next project deserves a better foundation.

Explore hosting built for your next chapter.

Explore hosting

Find your next answer.

Search published guides and articles.

Ctrl / ⌘ K to open · Esc to close