How to add ReCaptcha to a Next.js form
ReCaptcha is Google’s solution to spam and abuse with forms.
It’s an invaluable tool. First create an account on https://www.google.com/recaptcha if you haven’t already, and add your site domain.
Get the v2, and select the “I’m not a robot” checkbox:
You’ll get a site key, and a site secret.
Store the secret in your .env
file:
RECAPTCHA_SECRET=<....>
Now in your Next.js site install react-google-recaptcha
using npm:
npm install react-google-recaptcha
Now inside the page where you have the form, import it:
import ReCAPTCHA from 'react-google-recaptcha'
And you add it to the JSX:
<ReCAPTCHA size="normal" sitekey="<YOUR SITE KEY>" />
You should see it in the form:
Now if you try submitting your form it works because it’s not doing anything. Anyone, bots included, can submit the form successfully without even clicking the “I’m not a robot” button.
You need to validate the captcha server-side to make it useful.
I suppose you send the form to a Next.js API route. In there, add a validateCaptcha
method:
const validateCaptcha = (response_key) => {
return new Promise((resolve, reject) => {
const secret_key = process.env.RECAPTCHA_SECRET
const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secret_key}&response=${response_key}`
fetch(url, {
method: 'post'
})
.then((response) => response.json())
.then((google_response) => {
if (google_response.success == true) {
resolve(true)
} else {
resolve(false)
}
})
.catch((err) => {
console.log(err)
resolve(false)
})
})
}
Now in the request processing main code, add this before doing anything else:
if (!(await validateCaptcha(req.body['g-recaptcha-response']))) {
return res.redirect(`/captcha`)
}
delete req.body['g-recaptcha-response']
Create a /captcha
page in Next.js to redirect if the captcha check is invalid.
In the frontend, you should add some validation prior to submitting the form:
<form
method='post'
action='/api/new'
enctype='multipart/form-data'
onSubmit={event => {
if (grecaptcha.getResponse() === '') {
event.preventDefault()
alert("Please click <I'm not a robot> before sending the job")
}
}}
>
...
→ I wrote 17 books to help you become a better developer, download them all at $0 cost by joining my newsletter
→ JOIN MY CODING BOOTCAMP, an amazing cohort course that will be a huge step up in your coding career - covering React, Next.js - next edition February 2025