Skip to main content

Standard Integration

The most common way to use react-google-recaptcha is to import the default component, which automatically loads the Google reCAPTCHA script and handles initialization.
import ReCAPTCHA from "react-google-recaptcha";
import ReactDOM from "react-dom";

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

ReactDOM.render(
  <ReCAPTCHA
    sitekey="Your client site key"
    onChange={onChange}
  />,
  document.body
);
You need to sign up for an API key pair from Google to get your client site key.

Using the onChange Callback

The onChange callback is triggered when the user successfully completes the captcha. It receives the captcha token as its argument, which you should send to your backend for verification.
function onChange(token) {
  console.log("Captcha value:", token);
  // Send token to your backend for verification
  fetch('/api/verify-captcha', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token })
  });
}

Accessing Component Methods with Refs

You can access the component’s API methods using React refs:
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();
    this.props.onSubmit(recaptchaValue);
  }

  render() {
    return (
      <form onSubmit={this.onSubmit}>
        <ReCAPTCHA
          ref={this.recaptchaRef}
          sitekey="Your client site key"
          onChange={this.onChange}
        />
      </form>
    )
  }
}

Available Methods

  • getValue() - Returns the current captcha token value
  • getWidgetId() - Returns the reCAPTCHA widget ID
  • reset() - Forces a reset of the captcha
  • execute() - Programmatically invokes the challenge (for invisible reCAPTCHA)
  • executeAsync() - Promise-based version of execute()

Theme Customization

reCAPTCHA supports light and dark themes. The default is light.
<ReCAPTCHA
  sitekey="Your client site key"
  onChange={onChange}
  theme="light"
/>

Size Options

You can control the size of the reCAPTCHA widget with the size prop.
<ReCAPTCHA
  sitekey="Your client site key"
  onChange={onChange}
  size="normal"
/>
This is the default size - a standard reCAPTCHA widget.

Challenge Type

You can specify whether users solve an image or audio challenge. The default is image.
<ReCAPTCHA
  sitekey="Your client site key"
  onChange={onChange}
  type="audio"
/>
The audio type provides an accessible alternative for users with visual impairments.

Handling Expiration and Errors

reCAPTCHA tokens expire after a certain time. You should handle these cases:
function onExpired() {
  console.log("Captcha expired");
  // Optionally show a message to the user
}

function onErrored() {
  console.log("Captcha error - likely network issues");
  // Handle the error gracefully
}

<ReCAPTCHA
  sitekey="Your client site key"
  onChange={onChange}
  onExpired={onExpired}
  onErrored={onErrored}
/>
If you don’t provide an onExpired callback, the component will call onChange with null when the token expires.

Tab Index

Control the keyboard navigation order with the tabindex prop:
<ReCAPTCHA
  sitekey="Your client site key"
  onChange={onChange}
  tabindex={0}
/>
The default value is 0.

Complete Example

Here’s a complete form with all common options:
import React from "react";
import ReCAPTCHA from "react-google-recaptcha";

function ContactForm() {
  const recaptchaRef = React.useRef();
  const [formData, setFormData] = React.useState({ name: "", email: "" });

  const handleSubmit = async (e) => {
    e.preventDefault();
    const token = recaptchaRef.current.getValue();
    
    if (!token) {
      alert("Please complete the reCAPTCHA");
      return;
    }

    // Submit form with token
    await fetch('/api/contact', {
      method: 'POST',
      body: JSON.stringify({ ...formData, recaptchaToken: token })
    });

    // Reset the captcha
    recaptchaRef.current.reset();
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={formData.name}
        onChange={(e) => setFormData({ ...formData, name: e.target.value })}
        placeholder="Name"
      />
      <input
        type="email"
        value={formData.email}
        onChange={(e) => setFormData({ ...formData, email: e.target.value })}
        placeholder="Email"
      />
      <ReCAPTCHA
        ref={recaptchaRef}
        sitekey="Your client site key"
        theme="light"
        size="normal"
        onExpired={() => console.log("Expired")}
        onErrored={() => console.log("Error")}
      />
      <button type="submit">Submit</button>
    </form>
  );
}

Build docs developers (and LLMs) love