Skip to main content
Privy supports adding CAPTCHA to your login flow to prevent botting.
Enable CAPTCHA in the Privy Dashboard before implementing this feature.
CAPTCHA providers load content in the browser. Your app may need to update its Content Security Policy to allow CAPTCHA content. See the Content Security Policy guide for required directives.
Once CAPTCHA is enabled, import the Captcha component and place it as a peer to your login form: (When this component mounts, it will execute the invisible CAPTCHA.)
import {Captcha, useLoginWithEmail} from '@privy-io/react-auth';

const MyLoginForm = () => {
  const [email, setEmail] = useState('');
  const {sendCode, loginWithCode} = useLoginWithEmail();

  const handleSendCode = async () => {
    try {
      await sendCode(email);
    } catch (err) {
      // Captcha failures due to timeout or otherwise will show up here
      // in addition to possible network errors from the sendCode request
      //
      // The `sendCode` method from `useLoginWithSms` and `initOAuth` method
      // from `useLoginWithOAuth` work exactly the same way.
    }
  };

  return (
    <>
      <input type="text" onChange={(e) => setEmail(e.target.value)} />
      <button onClick={handleSendCode}>Send Code</button>
      <Captcha />
    </>
  );
};
That’s it! Whenever a user tries to log into your app, Privy will pre-validate the attempt with an invisible CAPTCHA. 🎉

Captcha providers

hCaptcha is supported by the React SDK starting in version [email protected].
Privy supports hCaptcha and Cloudflare’s Turnstile as CAPTCHA providers. Both providers enable invisible CAPTCHA verification during login.

hCaptcha risk tolerance

When using hCaptcha, your app can configure a risk tolerance level in the Privy Dashboard. This setting determines how strictly Privy blocks suspected bot behavior. By default, Privy uses a balanced setting that only blocks traffic above a mid-range risk score.