Stop contact form spam6 min read
reCAPTCHA alternatives for website forms
Compare reCAPTCHA alternatives for forms, from Turnstile and hCaptcha to proof-of-work and no captcha at all, then switch with a small, safe change.
Cloudflare Turnstile is the closest swap for reCAPTCHA: it is mostly invisible, uses the same site key and secret key pattern, and its server check takes the same parameters. hCaptcha suits sites that want image challenges from someone other than Google, and proof-of-work tools such as ALTCHA run with no third party at all. For many contact forms, a honeypot, content scoring and a rate limit make a captcha unnecessary.
Why people move off reCAPTCHA
reCAPTCHA still works. The reasons to replace it are usually about cost to visitors and to you. Version 2 shows image puzzles to some visitors, which is slow on phones and hard for people using screen readers. Version 3 is invisible but returns a score you must threshold yourself, with no challenge to fall back on. And reCAPTCHA is now a Google Cloud product: Google's billing docs list a free allowance of 10,000 assessments a month, with paid tiers above it.
Some teams also want fewer third-party scripts on their pages. Whether that matters for your privacy obligations is a question for your own legal review; this page only compares how the tools work.
The alternatives compared
| Option | What visitors see | Who verifies | Worth knowing |
|---|---|---|---|
| reCAPTCHA v2 | A checkbox, sometimes image puzzles | Your server, with Google | Familiar. The puzzles are the main complaint |
| reCAPTCHA v3 | Nothing | Your server, with Google | Returns a score from 0.0 to 1.0. You pick the cut-off and handle the grey zone |
| Cloudflare Turnstile | Usually nothing, sometimes a checkbox | Your server, with Cloudflare | No image puzzles. No cost for up to 20 widgets |
| hCaptcha | A checkbox, sometimes image puzzles | Your server, with hCaptcha | Similar to reCAPTCHA v2 in shape, from a different company. A free Basic plan, with paid Pro and Enterprise plans |
| Friendly Captcha | A small widget that solves a puzzle in the background | Your server, with Friendly Captcha | Proof of work instead of tracking signals. Free for small non-commercial sites, paid plans for everyone else |
| ALTCHA | A small widget that solves a puzzle in the background | Your own server only | Open source and self-hosted, so no third party. You run and maintain it |
| No captcha | Nothing | Your server | Honeypot, signed timing, content scoring and rate limits. Stops most bots, not all |
Every option except the last still depends on a server-side check. A widget on its own stops nothing, because a bot can post to your endpoint without loading the page.
What each option asks of people
Judge every option by the visitor who has the hardest time with it. Image puzzles are slow on a phone and hard or impossible for someone who can't see them well; audio fallbacks help some people and frustrate others. Invisible checks, like Turnstile's usual mode, reCAPTCHA v3 and proof-of-work widgets, ask nothing of most visitors, but they can still fail for people on privacy-focused browsers, strict networks or old devices. When that happens, the person needs a way forward: a visible checkbox, a clear message, or an email address to write to instead. A form that fails silently loses exactly the messages you never hear about.
Choose in two questions
- First ask whether bots get past invisible checks. If not, stay captcha-free with a honeypot, scoring and a rate limit.
- If they do, ask whether you can run server code. If you can, pick a widget such as Turnstile, hCaptcha or ALTCHA and verify it on your server.
- Without a server, post the form to a backend that verifies your Turnstile keys for you, or use a managed check that needs no keys.
Switch from reCAPTCHA to Turnstile
The two are close enough that the switch is a few lines on each side. Create a Turnstile widget in the Cloudflare dashboard for the same hostnames, then change the markup and the server check together.
| Piece | reCAPTCHA v2 | Turnstile |
|---|---|---|
| Script | https://www.google.com/recaptcha/api.js | https://challenges.cloudflare.com/turnstile/v0/api.js |
| Element | <div class="g-recaptcha" data-sitekey> | <div class="cf-turnstile" data-sitekey> |
| Token field | g-recaptcha-response | cf-turnstile-response |
| Verify URL | https://www.google.com/recaptcha/api/siteverify | https://challenges.cloudflare.com/turnstile/v0/siteverify |
| Verify parameters | secret, response, remoteip | secret, response, remoteip, idempotency_key |
<form action="/api/contact" method="POST">
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<div class="g-recaptcha" data-sitekey="RECAPTCHA_SITE_KEY"></div>
<button>Send</button>
</form>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>const form = await request.formData();
const body = new URLSearchParams({
secret: process.env.RECAPTCHA_SECRET_KEY!,
response: String(form.get("g-recaptcha-response") ?? ""),
});
const check = await fetch("https://www.google.com/recaptcha/api/siteverify", { method: "POST", body });
const { success } = (await check.json()) as { success: boolean };- This covers classic reCAPTCHA keys, verified at
siteverify. Keys created in Google Cloud are checked through the reCAPTCHA Enterprise assessments API instead; the Turnstile side is the same. - If you used v3, remove your score threshold. Turnstile answers pass or fail; check
actionin its answer instead. - Update your Content Security Policy: allow
https://challenges.cloudflare.cominscript-srcandframe-src, and drop the Google entries once nothing uses them. - Ship the markup and the server change in one deploy. A page with the new widget posting to a server that still expects
g-recaptcha-responsefails every submission.
Replacing reCAPTCHA with Ikiform
If your form posts to Ikiform, remove the reCAPTCHA widget entirely. Ikiform doesn't verify reCAPTCHA or hCaptcha tokens. The leftover g-recaptcha-response value would arrive as an extra field, or fail with 422 validation_failed as an unknown field if you defined the form's fields. Then pick what replaces it:
- Nothing extra. The honeypot, content scoring and rate limits run on every form. Many contact forms need no more.
- Spam check set to Ikiform. Cloudflare Turnstile, run by Ikiform, with no account or keys. A plain HTML post gets a short check page;
fetchcode callschallenge()from@ikiform/sdk. - Your own Turnstile keys. Keep your own widget on the page, paste the keys into the form's settings, and Ikiform verifies the token.
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="POST">
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
<button>Send</button>
</form>That form has no widget at all. With Spam check set to Ikiform, the human check happens on ikiform.com after the post, so your page loads no captcha script. The spam docs cover each mode.
Check it works
- Submit the form after the switch. The post is accepted and you saw at most a checkbox.
- Post to the endpoint with curl and no token. It is refused, which proves the server checks the new token.
- Search your pages for
g-recaptchaandrecaptcha/api.js. Nothing is left. - Open Submissions in the dashboard. The new submission is there with every field you sent.
- Nothing arrived? Switch the dashboard's status filter to Spam. Spam gets the same success answer as a real submission.
Gotchas
- Builder settings. Site builders with a built-in reCAPTCHA setting may require the element on every form while it is on. Turn the setting off before you remove the elements.
- Cached pages. Visitors with an old cached page still send
g-recaptcha-responsefor a while after you deploy. Expect a few failures, or accept both tokens for a day. - v3 scores in reports. If dashboards or alerts read the reCAPTCHA score, they go quiet after the switch. Update them.
Questions
For most forms, Cloudflare Turnstile: it is usually invisible, costs nothing at small scale and verifies with the same secret and response parameters. If you want no third party at all, a self-hosted proof-of-work tool such as ALTCHA works. Many contact forms need no captcha once a honeypot, scoring and a rate limit are in place.
Google's billing docs list a free allowance of 10,000 assessments a month, with paid tiers above that. Check Google's current pricing before you plan around it.
No. Ikiform verifies Cloudflare Turnstile only, either its own managed check or your own Turnstile keys. Remove other captcha widgets from forms that post to Ikiform.
Usually not. You change the script URL, the element's class, the token field name and the verify URL, and keep the same secret and response parameters. Deploy the page and the server change together.
Stuck on a step, or want a guide for your situation? Email hello@ikiform.com.