Skip to content

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")
    }
  }}
>
...

Here is how can I help you: