Skip to main content
The ReCAPTCHA component exposes several public methods that can be accessed via a React ref. These methods allow you to programmatically interact with the reCAPTCHA widget.

Accessing Methods via Ref

To use these methods, you need to create a ref and attach it to the component:
import React, { useRef } from "react";
import ReCAPTCHA from "react-google-recaptcha";

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

  const handleSubmit = () => {
    const token = recaptchaRef.current.getValue();
    console.log("Token:", token);
  };

  return (
    <form onSubmit={handleSubmit}>
      <ReCAPTCHA
        ref={recaptchaRef}
        sitekey="your-site-key"
      />
      <button type="submit">Submit</button>
    </form>
  );
}

Methods

getValue()

Returns the current response token from the reCAPTCHA widget. Signature:
getValue(): string | null
Returns:
  • string - The captcha response token if the user has completed the challenge
  • null - If the challenge hasn’t been completed or has expired
Example:
const recaptchaRef = React.createRef();

const handleSubmit = (event) => {
  event.preventDefault();
  const token = recaptchaRef.current.getValue();
  
  if (!token) {
    alert("Please complete the captcha");
    return;
  }
  
  // Send token to backend for verification
  fetch("/api/verify", {
    method: "POST",
    body: JSON.stringify({ token }),
    headers: { "Content-Type": "application/json" }
  });
};

<form onSubmit={handleSubmit}>
  <ReCAPTCHA
    ref={recaptchaRef}
    sitekey="your-site-key"
  />
  <button type="submit">Submit</button>
</form>

getWidgetId()

Returns the widget ID assigned by the reCAPTCHA API. This is useful for advanced integrations or debugging. Signature:
getWidgetId(): number | null
Returns:
  • number - The widget ID assigned by Google’s reCAPTCHA
  • null - If the widget hasn’t been initialized yet
Example:
const recaptchaRef = React.createRef();

const logWidgetInfo = () => {
  const widgetId = recaptchaRef.current.getWidgetId();
  console.log("Widget ID:", widgetId);
};

<>
  <ReCAPTCHA
    ref={recaptchaRef}
    sitekey="your-site-key"
  />
  <button onClick={logWidgetInfo}>Get Widget ID</button>
</>

reset()

Resets the reCAPTCHA widget, clearing any user input and allowing them to complete the challenge again. Signature:
reset(): void
Returns: void Example:
const recaptchaRef = React.createRef();

const handleError = (error) => {
  console.error("Submission failed:", error);
  // Reset captcha so user can try again
  recaptchaRef.current.reset();
};

const handleSubmit = async (event) => {
  event.preventDefault();
  const token = recaptchaRef.current.getValue();
  
  try {
    await fetch("/api/submit", {
      method: "POST",
      body: JSON.stringify({ token })
    });
  } catch (error) {
    handleError(error);
  }
};

<form onSubmit={handleSubmit}>
  <ReCAPTCHA
    ref={recaptchaRef}
    sitekey="your-site-key"
  />
  <button type="submit">Submit</button>
</form>

execute()

Programmatically invokes the reCAPTCHA challenge. This is required when using invisible reCAPTCHA (size="invisible"). Signature:
execute(): void
Returns: void
This method must be called for invisible reCAPTCHA. The onChange callback will be triggered with the token once the challenge is completed.
Example:
import React from "react";
import ReCAPTCHA from "react-google-recaptcha";

function InvisibleRecaptchaForm() {
  const recaptchaRef = React.createRef();

  const handleSubmit = (event) => {
    event.preventDefault();
    // Trigger invisible captcha
    recaptchaRef.current.execute();
  };

  const handleChange = (token) => {
    console.log("Captcha token:", token);
    // Submit form with token
    submitForm(token);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="email" />
      <ReCAPTCHA
        ref={recaptchaRef}
        size="invisible"
        sitekey="your-site-key"
        onChange={handleChange}
      />
      <button type="submit">Submit</button>
    </form>
  );
}

executeAsync()

Programmatically invokes the reCAPTCHA challenge and returns a Promise that resolves with the token. This provides a more modern, async/await friendly alternative to using execute() with the onChange callback. Signature:
executeAsync(): Promise<string>
Returns: Promise<string> - Resolves with the captcha token, or rejects if an error occurs Example:
import React from "react";
import ReCAPTCHA from "react-google-recaptcha";

function AsyncRecaptchaForm() {
  const recaptchaRef = React.useRef();

  const handleSubmit = async (event) => {
    event.preventDefault();
    
    try {
      // Execute captcha and wait for token
      const token = await recaptchaRef.current.executeAsync();
      
      // Submit form with token
      const response = await fetch("/api/submit", {
        method: "POST",
        body: JSON.stringify({ token }),
        headers: { "Content-Type": "application/json" }
      });
      
      if (response.ok) {
        console.log("Form submitted successfully");
      }
    } catch (error) {
      console.error("Captcha or submission failed:", error);
    } finally {
      // Reset for next submission
      recaptchaRef.current.reset();
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" name="email" required />
      <ReCAPTCHA
        ref={recaptchaRef}
        size="invisible"
        sitekey="your-site-key"
      />
      <button type="submit">Submit</button>
    </form>
  );
}

forceReset()

Forces a reset of the reCAPTCHA widget without requiring a widget ID. This is useful in edge cases where the widget might not be properly initialized. Signature:
forceReset(): void
Returns: void
This method bypasses the normal reset flow and should be used sparingly. In most cases, reset() is preferred.
Example:
const recaptchaRef = React.createRef();

const handleCriticalError = () => {
  // Force reset in case of critical error
  recaptchaRef.current.forceReset();
};

<ReCAPTCHA
  ref={recaptchaRef}
  sitekey="your-site-key"
/>

Complete Examples

Standard Form with Validation

import React, { useState, useRef } from "react";
import ReCAPTCHA from "react-google-recaptcha";

function ContactForm() {
  const recaptchaRef = useRef();
  const [error, setError] = useState("");

  const handleSubmit = async (event) => {
    event.preventDefault();
    setError("");

    // Get captcha token
    const token = recaptchaRef.current.getValue();
    
    if (!token) {
      setError("Please complete the reCAPTCHA");
      return;
    }

    try {
      const response = await fetch("/api/contact", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          token,
          name: event.target.name.value,
          email: event.target.email.value,
          message: event.target.message.value
        })
      });

      if (response.ok) {
        alert("Message sent successfully!");
        event.target.reset();
        recaptchaRef.current.reset();
      } else {
        throw new Error("Submission failed");
      }
    } catch (err) {
      setError("Failed to send message. Please try again.");
      recaptchaRef.current.reset();
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="name" required />
      <input type="email" name="email" required />
      <textarea name="message" required />
      
      <ReCAPTCHA
        ref={recaptchaRef}
        sitekey="your-site-key"
        onChange={() => setError("")}
      />
      
      {error && <div className="error">{error}</div>}
      <button type="submit">Send Message</button>
    </form>
  );
}

Invisible reCAPTCHA with executeAsync

import React, { useRef, useState } from "react";
import ReCAPTCHA from "react-google-recaptcha";

function InvisibleForm() {
  const recaptchaRef = useRef();
  const [isSubmitting, setIsSubmitting] = useState(false);

  const handleSubmit = async (event) => {
    event.preventDefault();
    setIsSubmitting(true);

    try {
      // Execute invisible captcha and get token
      const token = await recaptchaRef.current.executeAsync();
      
      // Submit with token
      await fetch("/api/submit", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ token })
      });
      
      alert("Success!");
    } catch (error) {
      alert("Error: " + error.message);
    } finally {
      setIsSubmitting(false);
      recaptchaRef.current.reset();
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" name="email" required />
      
      <ReCAPTCHA
        ref={recaptchaRef}
        sitekey="your-site-key"
        size="invisible"
      />
      
      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? "Submitting..." : "Submit"}
      </button>
    </form>
  );
}

Class Component Usage

If you’re using class components, you can still access methods via refs:
import React from "react";
import ReCAPTCHA from "react-google-recaptcha";

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

  handleSubmit = (event) => {
    event.preventDefault();
    const token = this.recaptchaRef.current.getValue();
    
    if (token) {
      this.props.onSubmit(token);
    }
  };

  handleError = () => {
    this.recaptchaRef.current.reset();
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <ReCAPTCHA
          ref={this.recaptchaRef}
          sitekey="your-site-key"
        />
        <button type="submit">Submit</button>
      </form>
    );
  }
}

Build docs developers (and LLMs) love