Implement Google reCAPTCHA in React App

Shejan Mahamud
7 min readApr 6, 2024

--

In this tutorial, we’re going to implement reCAPTCHA in a login form. Learn how to protect your React app from spam and abuse using reCAPTCHA.

Image: STATAMIC

What is reCAPTCHA?

Google reCAPTCHA is a technology developed by Google to distinguish between human users and automated bots on websites. It’s a system used to verify that the user interacting with a website is a human and not a malicious script or bot. reCAPTCHA presents users with challenges, such as selecting specific images from a grid or solving simple puzzles, to confirm their humanity.

Why we use reCAPTCHA?

Certainly, here are three key reasons why we use reCAPTCHA:

Preventing Spam and Abuse : reCAPTCHA helps prevent automated bots from flooding websites with spammy or malicious content, protecting the integrity of online platforms and user experiences.

Enhancing Security : By verifying that users are human, reCAPTCHA strengthens the security of websites and reduces the risk of unauthorized access, fraud, and other forms of cyberattacks.

Protecting User Experience : Spam and automated attacks can degrade the user experience on websites by inundating users with irrelevant or harmful content. reCAPTCHA helps maintain a clean and safe environment for users to interact with websites.

Implementing reCAPTCHA in Your React Application :

In this tutorial, we’ll create a login page to login users with their email address and password. Then we’ll add a reCAPTCHA to the login form to verify if the user is a human and filter out bots and spam.

Step-1:

npm create vite@latest recaptcha-project -- --template react
cd recaptcha-project

After this, Create a .env file in root folder :

recaptcha-project/
|- node_modules/
|- public/
|- src/
| |- components/
| |- assets/
| |- pages/
| |- App.vue
| |- main.js
|- .gitignore
|- .env
|- package.json
|- vite.config.js

Step- 2:

Now configure Google reCAPTCHA

Now configure the reCAPTCHA verification. To use Google’s reCAPTCHA, you must register a site on the reCAPTCHA admin console.

In the admin console, use your-project-name as the Label. Then, select reCAPTCHA v2 > “I’m not a robot” Checkbox as the reCAPTCHA type.

Here i’m using localhost in domain field. if you’re working in a production app then use your own domain. Now click on submit.

Now you have SITE KEY & SITE SECRET. This is so secret information don’t make this public. That’s why we created .env file. Go to .env file, and follow VITE documentation for .env configure. My .env file look like this:

VITE_SITE_KEY = YOUR SITE KEY
SITE_SECRET = YOUR SITE SECRET KEY

Note: .env file must be stored in root of app.

Step -3 :

We’re going to use a npm package to implement Google reCAPTCHA. Open your code editor and open your terminal(CTRL+J) and paste the below command and hit enter :

npm i react-google-recaptcha

Here is simple login page designed with tailwind css and react js :

import React from 'react';
import { FaGoogle } from "react-icons/fa";
import { FaXTwitter } from "react-icons/fa6";
import { MdOutlinePhoneAndroid } from "react-icons/md";
import { Link } from 'react-router-dom';
import ReCAPTCHA from "react-google-recaptcha";

const Login = () => {
return (
<div className='w-[90%] mx-auto my-20 flex flex-col items-center justify-center font-poppins'>
<h1 className="mb-3 text-4xl font-bold text-[#403F3F] uppercase tracking-wider">
Login
</h1>

<p className="mb-10 text-gray-500 font-medium text-sm">
Not Registered? Register <Link className="underline text-[#32B7C5] font-bold" to={'/register'}>Here</Link>
</p>
<form className='w-[30%] mx-auto flex flex-col items-center gap-5'>
<label className="input input-bordered flex items-center gap-2 w-full">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" className="w-4 h-4 opacity-70"><path d="M2.5 3A1.5 1.5 0 0 0 1 4.5v.793c.026.009.051.02.076.032L7.674 8.51c.206.1.446.1.652 0l6.598-3.185A.755.755 0 0 1 15 5.293V4.5A1.5 1.5 0 0 0 13.5 3h-11Z" /><path d="M15 6.954 8.978 9.86a2.25 2.25 0 0 1-1.956 0L1 6.954V11.5A1.5 1.5 0 0 0 2.5 13h11a1.5 1.5 0 0 0 1.5-1.5V6.954Z" /></svg>
<input type="text" className="grow" placeholder="Email" />
</label>
<label className="input input-bordered flex items-center gap-2 w-full">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" className="w-4 h-4 opacity-70"><path fillRule="evenodd" d="M14 6a4 4 0 0 1-4.899 3.899l-1.955 1.955a.5.5 0 0 1-.353.146H5v1.5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2.293a.5.5 0 0 1 .146-.353l3.955-3.955A4 4 0 1 1 14 6Zm-4-2a.75.75 0 0 0 0 1.5.5.5 0 0 1 .5.5.75.75 0 0 0 1.5 0 2 2 0 0 0-2-2Z" clipRule="evenodd" /></svg>
<input type="password" className="grow focus:outline-none focus:border-none" placeholder='Password' />
</label>
<button type='submit' className='w-full text-white bg-[#403F3F] py-3 rounded-lg uppercase font-medium'>Login</button>
<h1 className='font-medium text-sm'>Or Login With</h1>
<div className='w-full flex items-center gap-5 justify-center'>
<button type='button' className='w-10 h-10 bg-[#403F3F] rounded-lg text-white flex items-center justify-center'><FaGoogle /></button>
<button type='button' className='w-10 h-10 bg-[#403F3F] rounded-lg text-white flex items-center justify-center'><FaXTwitter /></button>
<button type='button' className='w-10 h-10 bg-[#403F3F] rounded-lg text-white flex items-center justify-center'><MdOutlinePhoneAndroid /></button>
</div>
</form>
</div>
)
}
export default Login

Import <ReCAPTCHA /> component from reCAPTCHA package :

import ReCAPTCHA from "react-google-recaptcha";

To test the reCAPTCHA on form submission, you need to call the getValue method on the reCAPTCHA instance and verify its value. For this, you need to keep a reference to the reCAPTCHA component, which you can do using the useRef hook.

Create a recaptcha reference using the useRef hook and assign it as the value for the ref prop on the ReCAPTCHA component and pass the siteKey prop and assign it to the import.meta.env.VITE_SITE_KEY so Google can recognize your reCAPTCHA :

const recaptcha = useRef(null);

<ReCAPTCHA sitekey={import.meta.env.VITE_SITE_KEY} ref={recaptcha}/>

To handle form submission, create a handleLogin function that’ll execute on the form submit event and verify the reCAPTCHA before form submission. To verify the reCAPTCHA, the handleLogin function calls the getValue method on the recaptcha ref object. The getValue method returns a token or undefined. If it’s a token, the user has verified themselves. Otherwise, you show them an toast. Add the handleLogin to the onSubmit event handler on the form element :

import React, { useRef } from 'react';
import ReCAPTCHA from "react-google-recaptcha";
import toast, { Toaster } from 'react-hot-toast';
import { FaGoogle } from "react-icons/fa";
import { FaXTwitter } from "react-icons/fa6";
import { MdOutlinePhoneAndroid } from "react-icons/md";
import { Link } from 'react-router-dom';

const Login = () => {

const recaptcha = useRef(null);

const handleLogin = (e) => {
e.preventDefault();
if(!recaptcha.current.getValue()){
toast.error('Please Submit Captcha')
}
}

return (
<div className='w-[90%] mx-auto my-20 flex flex-col items-center justify-center font-poppins'>
<h1 className="mb-3 text-4xl font-bold text-[#403F3F] uppercase tracking-wider">
Login
</h1>

<p className="mb-10 text-gray-500 font-medium text-sm">
Not Registered? Register <Link className="underline text-[#32B7C5] font-bold" to={'/register'}>Here</Link>
</p>
<form className='w-[30%] mx-auto flex flex-col items-center gap-5' onSubmit={handleLogin}>
<label className="input input-bordered flex items-center gap-2 w-full">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" className="w-4 h-4 opacity-70"><path d="M2.5 3A1.5 1.5 0 0 0 1 4.5v.793c.026.009.051.02.076.032L7.674 8.51c.206.1.446.1.652 0l6.598-3.185A.755.755 0 0 1 15 5.293V4.5A1.5 1.5 0 0 0 13.5 3h-11Z" /><path d="M15 6.954 8.978 9.86a2.25 2.25 0 0 1-1.956 0L1 6.954V11.5A1.5 1.5 0 0 0 2.5 13h11a1.5 1.5 0 0 0 1.5-1.5V6.954Z" /></svg>
<input type="text" className="grow" placeholder="Email" />
</label>
<label className="input input-bordered flex items-center gap-2 w-full">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" className="w-4 h-4 opacity-70"><path fillRule="evenodd" d="M14 6a4 4 0 0 1-4.899 3.899l-1.955 1.955a.5.5 0 0 1-.353.146H5v1.5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2.293a.5.5 0 0 1 .146-.353l3.955-3.955A4 4 0 1 1 14 6Zm-4-2a.75.75 0 0 0 0 1.5.5.5 0 0 1 .5.5.75.75 0 0 0 1.5 0 2 2 0 0 0-2-2Z" clipRule="evenodd" /></svg>
<input type="password" className="grow focus:outline-none focus:border-none" placeholder='Password' />
</label>
<button type='submit' className='w-full text-white bg-[#403F3F] py-3 rounded-lg uppercase font-medium'>Login</button>

<ReCAPTCHA sitekey={import.meta.env.VITE_SITE_KEY} ref={recaptcha}/>

<h1 className='font-medium text-sm'>Or Login With</h1>
<div className='w-full flex items-center gap-5 justify-center'>
<button type='button' className='w-10 h-10 bg-[#403F3F] rounded-lg text-white flex items-center justify-center'><FaGoogle /></button>
<button type='button' className='w-10 h-10 bg-[#403F3F] rounded-lg text-white flex items-center justify-center'><FaXTwitter /></button>
<button type='button' className='w-10 h-10 bg-[#403F3F] rounded-lg text-white flex items-center justify-center'><MdOutlinePhoneAndroid /></button>
</div>
</form>
<Toaster/>
</div>
)
}

export default Login

Sucessfully reCAPTCHA working on our react app.

Conclusion

In conclusion, integrating reCAPTCHA into a React application enhances security by verifying user interactions and preventing spam. By obtaining reCAPTCHA keys and using the react-google-recaptcha package, developers can seamlessly implement reCAPTCHA challenges in their forms and actions. This adds a crucial layer of protection against automated abuse while maintaining a user-friendly experience.

--

--

Shejan Mahamud
Shejan Mahamud

Written by Shejan Mahamud

Aspiring web developer passionate about MERN stack. Eager to create innovative and user-friendly web applications.

No responses yet