Turnstile vs reCAPTCHA on a contact form

Cloudflare Turnstile is the drop-in replacement for reCAPTCHA on a form: same job, same two-part shape (a widget on the page, one server call to verify the token), without asking real visitors to identify traffic lights and without verifying them against Google. If you are adding bot protection to a contact form today, Turnstile is the better default. Neither one is a spam filter, which is the part most people find out later.

The difference that matters

reCAPTCHA v2 reCAPTCHA v3 Turnstile
What the visitor does Clicks a checkbox, sometimes solves an image grid Nothing Nothing, or one click when managed mode decides the risk warrants it
Verified against Google Google Cloudflare
What you get back Pass or fail A score from 0.0 to 1.0 that you have to threshold yourself Pass or fail
Free quota 1,000 QPS or 1 million calls a month Same No published request cap
Over quota Visitors see “This site is exceeding reCAPTCHA quota” siteverify may fail open with a static score of 0.9 Not applicable

Vendor quotas and behaviour above were checked on 4 September 2026, against Cloudflare’s Turnstile docs and Google’s reCAPTCHA FAQ.

Two rows in that table are the whole argument.

reCAPTCHA v3 removes the friction and keeps everything else

The usual defence of reCAPTCHA is that v3 never interrupts anybody, and that is true. v3 is score-based. It watches the session and hands you a number, and the visitor never sees a widget.

What v3 does not remove is the rest of it. It still runs Google’s script on your page, it still sets the _GRECAPTCHA cookie that Google documents as necessary for risk analysis, and it still means every person who fills in your contact form is assessed by a third party. Google’s own FAQ suggests serving the script from www.recaptcha.net instead of www.google.com if you want to avoid picking up additional Google cookies, which tells you the concern is real enough to have a documented workaround.

It also moves work onto you. A score is not a decision. You have to pick the threshold, and you have to pick what happens in the middle band, and you get to discover empirically that legitimate users on a VPN score badly. v2 at least answered the question.

The quota is the part nobody reads

Standard reCAPTCHA is capped at 1,000 queries per second or 1 million calls per month. Cross it and the failure modes are documented, and they are both bad:

  • On v2, your visitors are shown “This site is exceeding reCAPTCHA quota”. Your contact form now displays a billing problem to a customer.
  • On v3, siteverify may fail open by returning a static score of 0.9. Your form keeps working. Your bot protection has silently stopped existing, and every submission now looks trustworthy.

Fail-open is the one to sit with. If you threshold at 0.5, an over-quota v3 key passes everything, and nothing in your logs says so.

reCAPTCHA Enterprise, which is the same product moved into a Google Cloud project, includes 10,000 assessments a month at no cost. That is a smaller free allowance than standard reCAPTCHA, on a service that needs a Cloud project to exist.

Turnstile’s free plan is bounded by features rather than by volume: up to 20 widgets, 10 hostnames per widget, and 7 days of analytics, with no published cap on verification requests. For a contact form, none of those limits are the one you hit.

Wiring Turnstile into a form

Two parts. The widget renders a hidden input named cf-turnstile-response inside your form:

<form action="/submit" method="POST">
  <input name="email" type="email" required />
  <textarea name="message"></textarea>
  <div class="cf-turnstile" data-sitekey="0x4AAA..."></div>
  <button>Send</button>
</form>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

Then your server posts that token to siteverify before it trusts anything:

const outcome = await fetch(
  "https://challenges.cloudflare.com/turnstile/v0/siteverify",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      secret: TURNSTILE_SECRET,
      response: token,
      remoteip: request.headers.get("CF-Connecting-IP"),
    }),
  },
);

if (!(await outcome.json()).success) return new Response("Nope", { status: 403 });

Three behaviours worth knowing before you debug them at midnight:

  • Tokens expire after 300 seconds. A visitor who opens your contact page, reads it for six minutes and then submits will fail verification. Long forms need the widget refreshed, not the timeout wished away.
  • Each token validates once. A retry with the same token comes back timeout-or-duplicate, which is why siteverify takes an optional idempotency_key.
  • Managed mode is the default and the right one. Non-interactive and invisible modes exist, but managed is the one that shows a checkbox only when the risk score calls for it.

None of this requires routing your site’s traffic through Cloudflare. Turnstile embeds on any host.

What neither of them stops

Here is the limit both products share, stated plainly: a bot check answers “is this a browser being driven by a human”, and that is not the same question as “is this submission worth reading”.

A headless browser with a good enough fingerprint passes. So does a real person in a real Chrome window, which is the entire business model of manual submission farms. Both of those clear Turnstile and reCAPTCHA and land in your inbox, and what arrives is grammatically correct, on-topic enough to read, and completely worthless: SEO outreach, agency pitches, crypto, someone’s cold email sequence with your form as the transport.

That is a content problem, not a bot problem, and no CAPTCHA of any generation solves it. The layer that does is a classifier that reads the submission and decides whether it is a real enquiry. The full stack, honeypot to bot check to classifier, is laid out in what a form backend is.

Where this leaves you

If you are choosing today: use Turnstile. Less friction than v2, no Google quota that fails open, no score to threshold, and a free tier whose limits are not the ones a contact form runs into.

If you are moving off reCAPTCHA, the swap is genuinely small. Same shape, different endpoint, and the token rules above are most of what changes.

FormRoute runs Turnstile and an AI classifier on the edge, before a submission is stored or forwarded, and configures the Turnstile side for you: your form gains no Cloudflare account and no siteverify call of your own, and blocked spam does not count against your monthly limit. There is markup for it in every stack we cover, from React to plain HTML.

It is in private access. Request an invite.

Get early access.

FormRoute is live in private access. Drop your email and we'll send your invite.

Free forever · 1,000 submissions/mo · unlimited forms