Migrate to RunxBuild today!! Deploy More while Spending Less

Calculate your savings
unxBuild

Netlify reCAPTCHA: Turning It On, Why Spam Still Gets Through, and What Actually Stops It

Sean

Platform Writer

Sep 21, 2026
8 min read

Adding reCAPTCHA to a Netlify form is one attribute, data-netlify-recaptcha="true", plus a div with the same attribute where the widget should appear. Netlify injects the challenge, verifies the token on submission, and rejects anything that fails. The part the docs say quietly and the support forum says loudly is that enabling reCAPTCHA disables the Akismet spam filter that was running on the form before, so a form that was catching most spam through content analysis now relies entirely on a checkbox that paid solving services defeat for fractions of a cent. If spam persists after enabling it, that is why, and the fix is not a stronger captcha but a different layer.

Netlify reCAPTCHA: Turning It On, Why Spam Still Gets Through, and What Actually Stops It

The keyword is a setup question with a troubleshooting question hiding inside it. The setup takes five minutes and is below. The troubleshooting is the more useful half, because the people searching this usually already turned reCAPTCHA on and are wondering why the submissions folder is still full of pharmacy links.

Table of contents

What Netlify Forms gives you before you touch anything

A form tagged with data-netlify="true" is detected at build time; Netlify rewrites it to post to its own endpoint, stores submissions, and can forward them by email or webhook. Two spam defences are on by default.

  • Akismet. Every submission is run through the Akismet content classifier. Anything flagged goes to a separate spam folder in the dashboard rather than triggering notifications. This catches the majority of comment-style spam with no configuration.
  • Rate limiting. Bursts from one source are throttled at the edge.

A third defence is one attribute away and costs nothing: the honeypot. Add data-netlify-honeypot="bot-field" to the form and a hidden input named bot-field. Humans never see it; bots that fill every field do, and any submission with a value in it is discarded. The honeypot does not disable Akismet, which makes it the first thing to add and the one most tutorials skip.

Enabling reCAPTCHA: the two-line version

<form name="contact" method="POST" data-netlify="true" data-netlify-recaptcha="true" data-netlify-honeypot="bot-field">
  <p hidden><label>Leave this empty: <input name="bot-field" /></label></p>
  <label>Email <input type="email" name="email" required /></label>
  <label>Message <textarea name="message" required></textarea></label>
  <div data-netlify-recaptcha="true"></div>
  <button type="submit">Send</button>
</form>

That is the whole setup for a plain HTML form. Netlify replaces the empty div with the reCAPTCHA v2 checkbox at build time and validates the response server-side. There is no site key to obtain and no secret to store, because Netlify uses its own keys.

If you want your own reCAPTCHA keys, for a branded widget or for v2 invisible mode, set SITE_RECAPTCHA_KEY and SITE_RECAPTCHA_SECRET as environment variables and render the widget yourself with the g-recaptcha-response field included in the POST. That is also the path for JavaScript-rendered forms, where the build-time rewrite cannot see the markup: render a hidden HTML copy of the form so Netlify registers it, then submit the real one with fetch including the token.

Why spam still arrives

Three reasons, in decreasing order of how often they are the cause.

  1. Akismet is now off. Netlify’s own documentation states that enabling reCAPTCHA disables the Akismet filter for that form. The captcha becomes the sole gate. Spam that Akismet would have quarantined is now either blocked by the checkbox or delivered to your inbox, and the second happens more than you would expect.
  2. Captcha-solving is a commodity. Services solve reCAPTCHA v2 challenges with human labour or models for well under a cent each. A spammer targeting contact forms at scale budgets for it. The checkbox raises the cost of spam from zero to nearly zero.
  3. The endpoint is public. Netlify Forms accept POSTs to the site’s own URL with the form name. A bot that has seen the form once can post directly, and if the reCAPTCHA token check passes because a solving service supplied one, the honeypot is the only thing left.

The practical consequence is that many people report more spam after enabling reCAPTCHA than before, because they traded a content filter for a checkbox. If that describes your form, the first experiment is to turn reCAPTCHA off, keep the honeypot, and see whether Akismet alone gets you back to an acceptable volume. For a low-traffic contact form it often does.

The layered setup that holds up

No single mechanism stops determined form spam. A combination does, and each layer catches what the previous one missed.

  • Honeypot for the naive bots that fill every field. Free, invisible, no false positives.
  • Akismet for content-based spam, so leave reCAPTCHA off unless you have a specific reason.
  • A time check in your own JavaScript: record when the form rendered, reject submissions that arrive within two seconds. Bots are fast; people are not.
  • A submit handler behind your own function for forms that matter. Post to a serverless function that checks the honeypot, verifies a token from a privacy-friendly challenge of your choosing, applies a rate limit per IP, and only then forwards the submission to Netlify Forms or to your own store. This moves the gate off the public endpoint and onto code you control.
  • Notification filtering as a last resort: route submissions to a webhook and apply your own classifier before anything reaches an inbox.

For most sites the first three are enough. The function-fronted approach is for the form that feeds a sales pipeline, where each spam entry costs someone a minute and each lost real lead costs more.

Where Netlify Forms stops being the right tool

Netlify Forms is a submission bucket with notifications. It is the right size for a contact page and a newsletter signup. It is the wrong size for a form whose submissions need to become rows a team works through, be searched, be deduplicated against a customer list, or trigger a workflow with more than one step. At that point the form is the front of an application, and the application needs a database, a small API, and probably a queue.

The migration is not dramatic. The same HTML form posts to a route on a small service instead of to Netlify, the service validates and writes a row to Postgres, and the notifications become a job that reads new rows. Spam handling moves into code you can change without a rebuild, and every layer above applies unchanged.

How this fits the rest of the stack

A form that outgrows a submission bucket usually needs three things at once: somewhere to run the handler, a database for the rows, and a way to see the requests that were rejected. The RunxBuild hosting calculator prices a small Node service and a managed Postgres together, which is the shape a serious form ends up as, and the runtime logs show every rejected submission beside every accepted one. For the static site the form lives on, static hosting on RunxBuild serves the page while the service handles the POST.

Useful related references:

FAQ

How do I add reCAPTCHA to a Netlify form?

Add data-netlify-recaptcha=true to the form element alongside data-netlify=true, and place an empty div with the same attribute where the widget should render. Netlify injects reCAPTCHA v2 at build time and verifies the response on submission. No keys are needed unless you want to use your own.

Why do I still get spam after enabling Netlify reCAPTCHA?

Enabling reCAPTCHA disables the Akismet content filter for that form, so the checkbox is the only defence, and captcha-solving services defeat it cheaply. Many sites see more spam after enabling it. Try disabling reCAPTCHA, keeping the honeypot, and letting Akismet filter content again.

What is the Netlify honeypot field?

A hidden input that humans never see but bots fill in. Add data-netlify-honeypot=bot-field to the form and a hidden input named bot-field; any submission with a value in that field is discarded. It works alongside Akismet and has no false positives.

Can I use my own reCAPTCHA keys on Netlify?

Yes. Set SITE_RECAPTCHA_KEY and SITE_RECAPTCHA_SECRET as environment variables, render the widget yourself, and include the g-recaptcha-response field in the submission. This is also required for JavaScript-rendered forms where the build-time rewrite cannot see the markup.

What is the most effective way to stop form spam on a static site?

Layers: a honeypot, Akismet or a similar content filter, a minimum time-on-page check, and for important forms a serverless function or small service in front of the submission endpoint that verifies a challenge token, rate-limits by IP and only then stores or forwards the submission.

#netlify recaptcha#netlify forms spam#netlify forms honeypot#data-netlify-recaptcha#stop form spam