Skip to main content

Basic Usage

The simplest way to use react-google-recaptcha is with the onChange callback, which fires when the user completes the CAPTCHA challenge.
1

Import the Component

Import ReCAPTCHA into your React component:
import ReCAPTCHA from "react-google-recaptcha";
2

Create the onChange Handler

Define a function to handle the CAPTCHA response token:
function onChange(value) {
  console.log("Captcha value:", value);
}
The value parameter contains the response token string if successful, or null if the CAPTCHA expired.
3

Render the Component

Add the ReCAPTCHA component to your form:
function App() {
  function onChange(value) {
    console.log("Captcha value:", value);
  }
  
  return (
    <div>
      <h1>My Form</h1>
      <ReCAPTCHA
        sitekey="your_site_key_here"
        onChange={onChange}
      />
    </div>
  );
}

Complete Form Example

Here’s a complete example of a contact form with reCAPTCHA protection:
import { useState } from "react";
import ReCAPTCHA from "react-google-recaptcha";

function ContactForm() {
  const [formData, setFormData] = useState({ name: "", email: "", message: "" });
  const [captchaToken, setCaptchaToken] = useState(null);

  function onCaptchaChange(value) {
    console.log("Captcha value:", value);
    setCaptchaToken(value);
  }

  function handleSubmit(e) {
    e.preventDefault();
    
    if (!captchaToken) {
      alert("Please complete the CAPTCHA");
      return;
    }

    // Send formData and captchaToken to your backend
    console.log("Submitting form with CAPTCHA token:", captchaToken);
    // fetch('/api/contact', {
    //   method: 'POST',
    //   body: JSON.stringify({ ...formData, captchaToken })
    // });
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        placeholder="Name"
        value={formData.name}
        onChange={(e) => setFormData({ ...formData, name: e.target.value })}
      />
      <input
        type="email"
        placeholder="Email"
        value={formData.email}
        onChange={(e) => setFormData({ ...formData, email: e.target.value })}
      />
      <textarea
        placeholder="Message"
        value={formData.message}
        onChange={(e) => setFormData({ ...formData, message: e.target.value })}
      />
      
      <ReCAPTCHA
        sitekey="your_site_key_here"
        onChange={onCaptchaChange}
      />
      
      <button type="submit">Submit</button>
    </form>
  );
}

Using Refs for Programmatic Control

For more control, you can use refs to access the component’s API methods:
import React from "react";
import ReCAPTCHA from "react-google-recaptcha";

class MyForm extends React.Component {
  constructor(props) {
    super(props);
    this.recaptchaRef = React.createRef();
  }

  onSubmit = () => {
    const recaptchaValue = this.recaptchaRef.current.getValue();
    if (!recaptchaValue) {
      alert("Please complete the CAPTCHA");
      return;
    }
    this.props.onSubmit(recaptchaValue);
  };

  render() {
    return (
      <form onSubmit={this.onSubmit}>
        <ReCAPTCHA
          ref={this.recaptchaRef}
          sitekey="your_site_key_here"
          onChange={(value) => console.log("Captcha value:", value)}
        />
        <button type="submit">Submit</button>
      </form>
    );
  }
}

Available Ref Methods

When using refs, you have access to these methods:
MethodDescription
getValue()Returns the current CAPTCHA response token
getWidgetId()Returns the widget ID assigned by reCAPTCHA
reset()Resets the CAPTCHA widget
execute()Programmatically invokes the challenge (for invisible reCAPTCHA)
executeAsync()Returns a Promise that resolves to the token

Invisible reCAPTCHA

Invisible reCAPTCHA doesn’t show a visible widget. You trigger the challenge programmatically:
import { useRef } from "react";
import ReCAPTCHA from "react-google-recaptcha";

function InvisibleForm() {
  const recaptchaRef = useRef();

  function onChange(value) {
    console.log("Captcha value:", value);
    // Submit form with value
  }

  function onSubmit(e) {
    e.preventDefault();
    recaptchaRef.current.execute();
  }

  return (
    <form onSubmit={onSubmit}>
      <input type="text" placeholder="Name" />
      <ReCAPTCHA
        ref={recaptchaRef}
        size="invisible"
        sitekey="your_site_key_here"
        onChange={onChange}
      />
      <button type="submit">Submit</button>
    </form>
  );
}
For invisible reCAPTCHA, you must configure your site key as “invisible” in the Google reCAPTCHA Admin Console.

Handling Expiration and Errors

CAPTCHA challenges expire after a period of time. Handle these cases with callbacks:
import { useState, useRef } from "react";
import ReCAPTCHA from "react-google-recaptcha";

function RobustForm() {
  const [captchaToken, setCaptchaToken] = useState(null);
  const recaptchaRef = useRef();

  function onChange(value) {
    setCaptchaToken(value);
  }

  function onExpired() {
    console.log("CAPTCHA expired");
    setCaptchaToken(null);
    alert("CAPTCHA expired. Please verify again.");
  }

  function onErrored() {
    console.log("CAPTCHA error");
    setCaptchaToken(null);
    alert("CAPTCHA error. Please try again.");
  }

  function handleSubmit(e) {
    e.preventDefault();
    
    if (!captchaToken) {
      alert("Please complete the CAPTCHA");
      return;
    }
    
    // Submit form
    console.log("Submitting with token:", captchaToken);
    
    // Reset CAPTCHA after submission
    recaptchaRef.current.reset();
    setCaptchaToken(null);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" placeholder="Your input" />
      
      <ReCAPTCHA
        ref={recaptchaRef}
        sitekey="your_site_key_here"
        onChange={onChange}
        onExpired={onExpired}
        onErrored={onErrored}
      />
      
      <button type="submit" disabled={!captchaToken}>
        Submit
      </button>
    </form>
  );
}

Backend Verification

Important: Always verify the CAPTCHA token on your backend server. Frontend validation alone is not secure.
After receiving the token from your frontend, verify it on your server:
Backend Example (Node.js)
const axios = require('axios');

async function verifyCaptcha(token) {
  const secretKey = process.env.RECAPTCHA_SECRET_KEY;
  
  const response = await axios.post(
    'https://www.google.com/recaptcha/api/siteverify',
    null,
    {
      params: {
        secret: secretKey,
        response: token,
      },
    }
  );
  
  return response.data.success;
}

// In your API endpoint:
app.post('/api/submit', async (req, res) => {
  const { captchaToken } = req.body;
  
  const isValid = await verifyCaptcha(captchaToken);
  
  if (!isValid) {
    return res.status(400).json({ error: 'CAPTCHA verification failed' });
  }
  
  // Process form submission
  res.json({ success: true });
});
See the Google reCAPTCHA verification documentation for more details on server-side verification.

Next Steps

Component API

Explore all available props and configuration options

Examples

See more real-world examples and use cases

Build docs developers (and LLMs) love