The error itself is by design. Every reCAPTCHA site
key carries a domain allowlist, and
localhost is not on it unless you put it
there. Google's
official FAQ
confirms both halves of the rule: localhost domains
are no longer supported by default, and you can add
localhost and 127.0.0.1 to a
key's domain list if you choose to. Threads on
Laracasts
and the
reCAPTCHA group
show how often that surprises people mid-sprint.
But "add localhost to the production key" is the worst of the available fixes, and it is the one most teams reach for first.
Option 1: The Official Test Keys (Best for Most Development)
Google publishes a dedicated key pair for automated and local testing, documented in the reCAPTCHA FAQ:
Site key: 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI Secret key: 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe
These keys work on any domain, always render the "No
CAPTCHA" path, and every
siteverify call against the test secret
succeeds. The widget shows a warning banner reminding
you it is for testing — which is a feature, not a bug:
if you ever see that banner in production, you know
immediately that a test configuration leaked.
- No admin-console changes needed. New contributors clone the repo and the form works — the pain that drove projects like freesound's issue #879 to adopt exactly this setup for development.
- Deterministic CI. End-to-end tests can submit forms without flaky challenge solving, because the test pair always passes verification.
-
One caveat: because verification
always succeeds, test keys cannot exercise your
failure-handling code. Cover the "verification
failed" branch with a unit test that stubs the
siteverifyresponse instead.
Option 2: A Dedicated Development Key
If you need realistic widget behavior locally — real
challenges, real scores for reCAPTCHA v3 — create a
separate key in the
admin console
with localhost and
127.0.0.1 in its domain list, and keep it
out of production entirely. Community guides such as
LocalWP's localhost thread
converge on the same advice: never add localhost to
the key your live site uses. Anyone running code on
their own machine would be operating inside your
production property — their traffic, their
experiments, your analytics.
Wire the choice through environment configuration, not code branches:
# .env.development RECAPTCHA_SITE_KEY=your-dev-key RECAPTCHA_SECRET=your-dev-secret # .env.production RECAPTCHA_SITE_KEY=your-prod-key RECAPTCHA_SECRET=your-prod-secret
The anti-pattern to avoid is the boolean bypass —
if (env.SKIP_CAPTCHA) return true; —
because a flag is exactly one misconfigured deploy
away from disabling verification in production
silently. Swapping keys per environment fails safe: if
the wrong key ships, the widget errors loudly instead
of waving every bot through.
Making End-to-End Tests Pass Honestly
CAPTCHA and test automation are natural enemies — the whole point of the widget is to stop exactly the kind of scripted browser your test suite drives. Teams resolve that tension in one of three ways, and only one of them is safe:
- Test keys in the test environment (safe). Point your E2E environment at the official test pair. Playwright or Cypress fills the form, the widget auto-passes, the server verifies against the test secret, and the whole submission path — including your token plumbing — is exercised for real.
- Conditional bypass in application code (risky). A "skip verification when NODE_ENV=test" branch means your production binary contains a door that configuration can open. Incidents in this category are boring and devastating: a copied env file, a typo'd deploy variable, and the door is open in production while every dashboard stays green.
- Solving services or stealth plugins (wrong). If your tests need CAPTCHA-solving tooling to pass, you are testing Google's bot detection, not your application — and normalizing the same tooling attackers use.
The test-key approach has one more virtue: it keeps your test traffic out of your production reCAPTCHA analytics. Score-based v3 tunes its picture of "normal" from the traffic it sees; flooding the production key with headless-browser submissions from CI distorts the very baseline that decides how real users get scored.
Staging, Tunnels, and the Hostnames In Between
Between localhost and production live the hostnames that cause the subtler failures: staging subdomains, preview deployments, and tunnel URLs from tools like ngrok. Each is just another domain to reCAPTCHA, so each needs to be covered by whichever key that environment uses — a dev key for previews, or explicit entries on a staging key. If your staging site shows the invalid-domain banner after a clone, that is the same root cause we walk through in our invalid-domain troubleshooting guide.
Two operational rules keep this manageable. First,
document which key belongs to which environment in the
repo itself, next to the env templates, so the mapping
survives team turnover. Second, make your deploy
checklist assert the production key in the rendered
HTML — a one-line smoke test that has caught more
leaked test keys than any code review. And remember
that server-side verification is where enforcement
actually happens; if your
siteverify handling is shaky, fixing the
keys will not save you — see our guide to
debugging invalid-input-response tokens.
It is also worth asking how much of this ceremony your verification layer should require. Behavioral approaches such as rCAPTCHA verify users from interaction signals on the page, which simplifies the local-development story — though any verification system, ours included, still deserves per-environment configuration and a test mode that cannot reach production unnoticed.
People Also Ask: reCAPTCHA Development FAQ
Does reCAPTCHA work on localhost?
Not by default. Localhost is excluded from new site
keys, so the widget shows a domain error. Either use
Google's published test key pair, which works on any
domain, or create a development-only key with
localhost and 127.0.0.1
added to its domain list.
What are the official reCAPTCHA test keys?
Google's FAQ publishes a test pair: site key
6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
and secret
6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe.
All challenges auto-pass and all verifications
succeed, with a visible warning banner so the keys
cannot be mistaken for production.
Should I add localhost to my production site key?
No. It lets any machine running your code operate inside your production reCAPTCHA property, mixing developer traffic into your real risk and analytics data. Use the test keys or a dedicated dev key instead.
How do I test the failure path if test keys always pass?
Stub the server-side verification response in unit
tests: have your siteverify client return
success: false with error codes like
invalid-input-response and assert your
form rejects the submission gracefully. End-to-end
tests with test keys then cover the success path.
Conclusion
"Localhost is not in the list of supported domains" is reCAPTCHA working as designed — the question is how you route around it without weakening production. Use the official test keys for everyday development and CI, a dedicated dev key when you need realistic challenges, and per-environment configuration instead of bypass flags. The goal is a setup where the lazy path and the safe path are the same path — and where any test artifact that reaches production announces itself instead of silently letting the bots in.
Sources & Further Reading
- Google for Developers: reCAPTCHA FAQ (test keys and localhost guidance)
- Google reCAPTCHA admin console
- Google reCAPTCHA group: "Will reCAPTCHA work on localhost for debugging?"
- Laracasts: localhost not in supported domains thread
- MTG/freesound issue #879: use test keys for reCAPTCHA on localhost
- LocalWP community: localhost reCAPTCHA thread