Every captcha comparison you can find measures the same thing: how much spam gets through. That is the easy half of the question. The hard half — the one that costs money — is what happens to the real customer who gets blocked by accident. A contact form submission that never arrives does not generate a bounce, an error, or a support ticket. It simply does not exist, and nobody on your side ever knows it was there.
That is the angle we took for this comparison. We installed Must-Have Captcha on a test site, deliberately produced a false positive from a submission that any human would recognise as a genuine enquiry, and then tried to get that lead back. Then we looked at what Google reCAPTCHA offers for the same situation, and at what each option costs the visitors who never do anything wrong.
Two different places to make the decision
The two products are built on the same broad idea — score the visitor’s behaviour instead of asking them to solve a puzzle — but they run that logic in different places, and that difference drives almost everything else.
reCAPTCHA loads Google’s script on your page, collects signals in the browser, and sends a token to Google. Your server then calls Google’s API to exchange that token for a verdict (v2) or a score (v3). The decision is made on Google’s infrastructure, and the raw signals never touch your server.
Must-Have Captcha collects interaction signals with a small script of its own, stores them in a signed cookie on the visitor’s browser, and scores the request in PHP on your own server when the POST arrives. According to the plugin documentation, the cookie holds base64-encoded JSON with a SHA-256 signature tied to the user agent, and the score is compared against a threshold — 15 for Basic, 30 for Normal, 60 for Strict. If the score is below the threshold, the request is blocked with a 403 before WordPress processes it.
| Must-Have Captcha 0.3.5 | Google reCAPTCHA (v2 / v3) | |
|---|---|---|
| Where the decision is made | Your server, in PHP | Google’s infrastructure |
| Third-party requests on your pages | None | google.com and gstatic.com |
| Setup | Activate; works with defaults | Register the site, copy site key and secret key |
| Visitor friction | Invisible; no widget | v2: checkbox, sometimes an image challenge. v3: badge only |
| Blocked submissions | Stored and reviewable in wp-admin | Not stored; the submission is gone |
| Recovering a false positive | One click (“Accept”) | No built-in path; needs custom development |
| Per-URL / per-IP rules | Built in (Custom Rules) | Score thresholds in your own code |
The last two rows are the ones this article is about.
How we tested
All measurements below come from one WordPress install, so the numbers are comparable with each other. They are not benchmarks of your site, and a different threshold or a different visitor mix will produce different scores.
- Environment: WordPress 7.1, PHP 8.3.30, Apache, no page cache, Must-Have Captcha 0.3.5.
- Protection level: Normal — the shipped default, threshold 30.
- Forms: Contact Form 7 6.1.7 with Flamingo storing the entries, and the stock WordPress comment form on a blog post. Two of the most ordinary things you can put on a WordPress site.
- Submissions: sent with
curl, each one carrying a signed interaction cookie built to represent a specific visitor profile (or no cookie at all, for the script-bot case), plus a matching user agent and client IP. - reCAPTCHA payload: measured by loading Google’s own public reCAPTCHA v2 demo page in a Chromium browser and recording every request to
google.comandgstatic.com.
Before any of that, here is what the protected Contact Form 7 form looks like to a visitor. There is no checkbox, no badge, and nothing to click — the only sign the plugin is there is a 4.6 KB script in the page source.

And here is the settings screen. Three protection levels, a handful of toggles, and — relevant to the comparison — no fields for an API key or a secret.

Six submissions, five blocks
We sent six requests: four spam-shaped ones, and two from profiles meant to represent real people. Here is what the plugin scored them.
| Submission | Profile | Score | Result |
|---|---|---|---|
| Contact Form 7 | Bot with no JavaScript at all (no cookie) | 0 | Blocked |
| Contact Form 7 | Headless browser, form filled in 0.4 s, spam content | −71 | Blocked |
| Contact Form 7 | Form filler that also filled the hidden honeypot field | −1000 | Blocked |
| Contact Form 7 | Real enquiry from a phone, text pasted, 2.4 s on page | 13 | Blocked |
| Blog comment | Real reader on a tablet, pasted comment, no typing signals | 20 | Blocked |
| Contact Form 7 | Real enquiry from a desktop, typed, 74 s on page | above threshold | Delivered |
The three spam cases behaved as you would hope. The honeypot is the bluntest of them: the plugin injects a hidden field into forms, and any submission that fills it in is scored −1000 immediately. A request that arrives with no interaction cookie at all — the signature of a script that never ran your JavaScript — scores 0, which sits below the threshold at every protection level, including Basic.

Meanwhile the visitor whose submission was blocked sees this, and nothing else:

The two that should not have been blocked
Look at rows four and five. Neither of those profiles is exotic. The contact form submission came from an iPhone, from someone who wrote the message somewhere else, pasted it in, and hit send within a few seconds. It scored 13 against a threshold of 30 — not because the content looked like spam, but because the session produced very little of what the scoring engine reads as human: no typing, no mouse movement, a short time on the page and several pastes.
This is the shape of a false positive that behaviour-based protection will always be capable of producing, no matter whose engine is doing the scoring. People paste. People arrive from a bookmark, fill in one field and leave. People use assistive technology that does not generate the mouse events a scoring model expects. Turn the protection up and you catch more spam and more of these; turn it down and you catch less of both. There is no threshold that makes the problem disappear.
Where the products differ is what is available to you afterwards. In Must-Have Captcha the blocked submission is still there, with everything the visitor sent:

A human reading that screen needs about three seconds to decide it is a real enquiry from a dental practice asking for a quote. The question is what you can do about it.
Replaying a blocked submission
The Accept button at the top of that panel replays the request. We clicked it, confirmed the dialog, and the row disappeared from the list.

More usefully, the enquiry itself arrived. Contact Form 7 processed it exactly as it would have the first time, and the lead that was invisible sixty seconds earlier is now sitting in Flamingo’s inbox next to the submission that had passed normally:

We repeated it with the blocked comment, and it behaved exactly the way a genuine comment would have: it went into the moderation queue rather than straight onto the post.

What “replay” actually does
This is worth understanding before you rely on it, because it is not a “mark as approved” flag. When a request is blocked, the plugin stores the POST body, the request headers and the cookies alongside the score. Accepting it makes your own server send that stored request back to the original URL with a one-time key, and the plugin rebuilds $_POST, the headers and the cookies from the stored copy — including the original Content-Type, which is what lets a REST-based form endpoint accept it — and sets an internal bypass flag so the captcha does not block it a second time. From that point WordPress runs the request normally: whatever plugin, form handler or hook would have processed it the first time processes it now. The stored copy is only deleted once the replay has actually gone through.
That design has three consequences worth knowing about.
- Submissions containing sensitive data cannot be replayed. Fields matching patterns like password, card number, CVV or token are masked before storage, and the documentation states that a request whose data was masked is not replayable — the original values were never kept. In practice this means contact forms, registrations and enquiries are recoverable; a blocked login or checkout submission is not.
- The replay comes from your server. Anything downstream that records the client IP will see the server’s own address rather than the visitor’s, because the request is genuinely re-sent from the site itself. The original IP is still visible in the blocked-request log.
- It only works for submissions that were actually blocked. If a form endpoint is on your Custom Rules list as “Block & Ignore”, nothing is stored, and there is nothing to replay. That is the intended trade-off for high-volume endpoints you never want logged.
- A replay that fails does not lose the submission. We tested this deliberately by deactivating the form plugin between the block and the replay: the endpoint answered 404, and instead of a success message the admin got “The request could not be replayed (the target endpoint answered with HTTP 404). It has been kept in the log so nothing is lost.” — with the row still in the list, ready to try again once the cause is fixed.
In our test the replay worked for both submission styles we threw at it: Contact Form 7’s REST endpoint, which posts multipart/form-data, and the stock WordPress comment form, which posts a classic form-encoded request. Both arrived intact.
What reCAPTCHA gives you for the same false positive
Nothing equivalent, and that is a consequence of the architecture rather than an oversight.
With reCAPTCHA v2, a visitor who fails the challenge never gets a valid token, so the form is never submitted. There is no request for your site to store, review or replay — the data stayed in the visitor’s browser and left with them when they closed the tab. Google’s admin console will tell you how many challenges were served and how many were solved; it will not tell you who gave up, and it cannot give you back what they were typing.
With reCAPTCHA v3 the picture is slightly better, because the form does reach your server together with a score between 0.0 and 1.0. What happens next is entirely your code’s decision. If your form plugin is configured to reject submissions below the threshold, the submission is discarded — the same outcome. If you build the alternative yourself, you can store low-score submissions in a review queue and process them manually later. That is a perfectly reasonable pattern, and if you have a developer on the project it is not a big piece of work. It is just work that you do, and maintain, rather than a feature you switch on.
The practical version of the difference: with Must-Have Captcha, reviewing false positives is a tab in wp-admin. With reCAPTCHA, it is a ticket in your backlog.
What each one costs the visitors who did nothing wrong
False positives are the expensive failure. Page weight is the everyday one, and it is easy to measure precisely.
We loaded the protected contact form and recorded every request the browser made. Must-Have Captcha added exactly one: its own captcha.js, 4,632 bytes uncompressed (about 2 KB gzipped), served from the site’s own domain. The page made no requests to any third-party host at all.
Then we loaded Google’s official reCAPTCHA v2 demo page and recorded every request to google.com and gstatic.com. There were 13 of them, covering seven distinct resources.
| Resource | Decoded size |
|---|---|
recaptcha__en.js | 779,653 bytes (≈320 KB gzipped over the wire) |
styles__ltr.css | 82,980 bytes |
api2/anchor (widget iframe) | 54,797 bytes |
api2/bframe (challenge iframe) | 17,194 bytes |
api.js (loader) | 1,548 bytes |
| logo + web worker | 2,330 bytes |
| Total, unique resources | ≈938 KB decoded, across 13 requests to two third-party hosts |

Two caveats so the comparison stays honest. Those resources are cached aggressively and shared across every site that uses reCAPTCHA, so a returning visitor who has met reCAPTCHA elsewhere may pay very little of that cost. And reCAPTCHA v3 skips the challenge iframe, so its footprint is smaller than v2’s — though it still loads the same main script. What does not change is the number of hosts involved: one of these approaches keeps everything on your domain, and the other does not.
Friction, privacy and price
Friction. reCAPTCHA v2 asks the visitor to do something. Most of the time that is one click, but “most of the time” is doing real work in that sentence — visitors on VPNs, on shared IPs, or with strict privacy settings meet the image challenge far more often, and image challenges are exactly the point where people abandon forms. v3 removes the interaction and shows a badge instead. Must-Have Captcha shows nothing at all; the visitor’s first sign of it is the blocked page, if they ever see it.
Privacy. reCAPTCHA sends visitor signals to Google, which makes it a third-party data transfer you have to account for in your privacy policy and, in the EU, in your consent handling. Must-Have Captcha keeps the signals in a first-party cookie and scores them on your server, so there is no transfer to disclose — and if you run Must-Have Cookie, its cookie is registered as essential so protection keeps working before consent. The flip side is worth stating plainly: the blocked-request log stores the contents of blocked submissions, which is personal data sitting in your database. The Expiry setting (from one day to “keep forever”) is how you control that, and one week is a sensible default for most sites.
Price. reCAPTCHA Essentials is free up to 10,000 assessments per month, and Google’s pricing page notes that the free allowance is counted per organisation across all accounts and sites, not per site. Above that it is a flat $8 per month to 100,000 assessments, then $1 per 1,000. Must-Have Captcha is $6.99 per year for one site, $12.99 per year for five, or included in the Must-Have Pack at $59.99 per month with every other Must-Have plugin.
| Must-Have Captcha | reCAPTCHA | |
|---|---|---|
| Entry price | $6.99 / year, 1 site | Free to 10,000 assessments / month |
| Five sites | $12.99 / year | Free allowance is shared across all of them |
| Higher volume | Same price | $8 / month to 100k, then $1 per 1,000 |
| Front-end payload measured | 1 request, 4.6 KB, same domain | 13 requests, ≈938 KB decoded, two Google hosts |
| Recovering a blocked lead | Built in | Build it yourself (v3) or not possible (v2) |
Where reCAPTCHA is still the stronger choice
A comparison that only points one way is not much use, so: there are real reasons to stay with Google.
- Signal scale. Google sees traffic from an enormous share of the web, and cross-site reputation is a genuinely powerful signal that no self-hosted plugin can reproduce. Against a determined, well-resourced attacker that matters.
- An escalation step. reCAPTCHA can present a challenge to a borderline visitor and let them prove themselves. Must-Have Captcha has one outcome for a low score: block, and rely on you reviewing the log afterwards. For a site where a blocked visitor would simply give up and never come back, being able to offer them a puzzle is a real advantage.
- It is already integrated everywhere. Nearly every form plugin ships a reCAPTCHA field. If your stack is built around that, switching is a project rather than an afternoon.
- Zero cost at low volume, if a shared 10,000-assessment allowance covers your whole portfolio.
Who should choose what
Choose Must-Have Captcha if your forms carry enquiries you cannot afford to lose quietly — quote requests, bookings, applications, B2B leads — or if you would rather not add a third-party data transfer to a site you are keeping GDPR-tidy. It also suits agencies managing several small sites, where a five-site licence costs less per year than an hour of support time spent explaining a missing enquiry.
Stay with reCAPTCHA if your forms are low-value and high-volume (newsletter sign-ups, comment forms on a large publisher site), if you are already under sustained targeted attack and want Google’s cross-site reputation data, or if you specifically want the option to challenge a suspicious visitor instead of blocking them outright.
Consider both. They are not mutually exclusive. Some sites put reCAPTCHA on the login and registration flows, where challenges are acceptable and replay is not possible anyway, and use a self-hosted scorer with a review log on the forms that carry revenue.
Frequently asked questions
Does replaying a blocked submission send the emails too?
Yes, as far as your form handler is concerned nothing is different. The request is re-sent to the original URL and processed by WordPress normally, so notification emails, entry storage and any hooks your form plugin fires all run at that point — just later than the visitor expected.
Can I replay a blocked login or checkout?
No, and that is deliberate. Passwords, card numbers and similar fields are masked before the request is stored, and a request whose data was masked is marked as not replayable because the original values no longer exist. For those flows the answer is a Custom Rule that relaxes protection on the endpoint, not a replay.
How long are blocked submissions kept?
It is a setting: one day, one week, one month, one year, or forever, cleaned up by a daily cron job. Since the log contains the contents of the blocked submissions, treat it like any other store of personal data and pick the shortest window that still gives you time to review.
Will a self-hosted captcha catch as much spam as Google?
For ordinary automated spam — the scripts and form fillers that make up the overwhelming majority of what hits a WordPress site — behavioural scoring plus a honeypot is very effective, and our test cases were all stopped comfortably below the threshold. For a targeted attack by someone who is specifically interested in your site, Google’s cross-site data is an advantage. Most sites are dealing with the first problem, not the second.
What happens if I set the protection level too high?
You block more real people — and, unlike with most captchas, you can see exactly who. That is arguably the most useful way to use the blocked-request log: run Strict for a week, read what got caught, and tune down (or add a Custom Rule for a specific URL) based on what you actually see rather than on guesswork.
Do I need to add anything to my forms?
No. There is no shortcode or field to place — the plugin validates POST requests site-wide once it is active, which is also why per-URL Custom Rules exist for endpoints that should be treated differently.
The takeaway
Both products will stop the spam that arrives at an ordinary WordPress site. Neither can promise it will never block a real person, because no behaviour-based system can — the profiles that trip it up are ordinary ones, and in our test a genuine quote request from a phone scored 13 against a threshold of 30.
What differs is the recovery path. One architecture makes the decision on someone else’s servers and leaves you with a number; the other makes it on yours, keeps the evidence, and gives you a button. If the forms you are protecting carry enquiries that are worth money, that button is the part of the comparison worth thinking hardest about — and the failure mode it addresses is precisely the one you would otherwise never find out about.
If you want to look closer: the Must-Have Captcha documentation covers the scoring signals, filters and Custom Rules in detail, and we have written separately about reviewing and recovering blocked submissions, when to use Custom Rules, setting the plugin up, and why behaviour-based protection beats puzzles. If losing form submissions is a recurring worry rather than a one-off, it is also worth reading how to monitor your forms so you find out when they break for other reasons too. Google’s own reCAPTCHA v3 documentation and its current pricing page are the right sources for the other side.

