---
title: CAPTCHA
description: Use the plugin to add CAPTCHA to your authentication flow.
sidebar:
  order: 6
---

## Overview

This following tutorial shows you how to add CAPTCHA validation to your authentication flows.
The guide makes use of the plugins functionality.
A new abstraction layer aimed to simplify how you can add new features in your **SuperTokens** integration.

## Before you start

The plugin supports only the `React` and `NodeJS` SDKs. 
Support for other platforms is under active development.

You can use the plugin with the following CAPTCHA providers:
- [Google reCAPTCHA v2](https://developers.google.com/recaptcha/docs/display)
- [Google reCAPTCHA v3](https://developers.google.com/recaptcha/docs/v3)  
- [Cloudflare Turnstile](https://www.cloudflare.com/en-gb/application-services/products/turnstile)

Make sure to have the appropriate provider keys before starting the tutorial.

The implementation is in early stages and APIs might change.
For more information on how plugins work refer to the [references page](/references/plugins/introduction).

## Steps

### 1. Initialize the frontend plugin

#### 1.1 Install the plugin

```bash
npm install @supertokens-plugins/captcha-react
```

#### 1.2 Update your frontend SDK configuration

```typescript
import SuperTokens from "supertokens-auth-react";
import CaptchaPlugin from "@supertokens-plugins/captcha-react";

SuperTokens.init({
  appInfo: {
    appName: "...",
    apiDomain: "...",
    websiteDomain: "...",
  },
  recipeList: [
    // your recipes
  ],
  experimental: {
    plugins: [
      CaptchaPlugin.init({
        type: "reCAPTCHAv3", // or "reCAPTCHAv2" or "turnstile"
        captcha: {
          sitekey: "your-site-key",
          // Additional configuration based on the captcha provider
        },
      }),
    ],
  },
});
```

### 2. Initialize the backend plugin

#### 2.1 Install the plugin

```bash
npm install @supertokens-plugins/captcha-nodejs
```

#### 2.2 Update your backend SDK configuration


```typescript
import SuperTokens from "supertokens-node";
import CaptchaPlugin from "@supertokens-plugins/captcha-nodejs";

SuperTokens.init({
  supertokens: {
    connectionURI: "...",
  },
  appInfo: {
    appName: "...",
    apiDomain: "...",
  },
  recipeList: [
    // your recipes
  ],
  experimental: {
    plugins: [
      CaptchaPlugin.init({
        type: "reCAPTCHAv3", // or "reCAPTCHAv2" or "turnstile"
        captcha: {
          secretKey: "your-secret-key",
        },
      }),
    ],
  },
});
```

:::info
If you are using a captcha input that renders an input on the frontend, you will have to [disable the use of shadow DOM](/references/frontend-sdks/prebuilt-ui/shadow-dom) when you initialize the SDK.
:::

### 3. Customize the plugin

By default, the plugin performs CAPTCHA validation on the following authentication flows:

| Recipe          | Authentication Flow        | Forms                                                                                  | Pre-API Hook Action         | API Function                     |
| --------------- | -------------------------- | -------------------------------------------------------------------------------------- | --------------------------- | -------------------------------- |
| `EmailPassword` | User sign in               | `EmailPasswordSignInForm`                                                              | `EMAIL_PASSWORD_SIGN_IN`    | `signInPOST`                     |
| `EmailPassword` | User registration          | `EmailPasswordSignUpForm`                                                              | `EMAIL_PASSWORD_SIGN_UP`    | `signUpPOST`                     |
| `EmailPassword` | Password reset request     | `EmailPasswordResetPasswordEmail`                                                      | `SEND_RESET_PASSWORD_EMAIL` | `generatePasswordResetTokenPOST` |
| `EmailPassword` | Password reset submission  | `EmailPasswordSubmitNewPassword`                                                       | `SUBMIT_NEW_PASSWORD`       | `passwordResetPOST`              |
| `Passwordless`  | Generate verification code | `PasswordlessEmailForm` and `PasswordlessPhoneForm` and `PasswordlessEmailOrPhoneForm` | `PASSWORDLESS_CREATE_CODE`  | `createCodePOST`                 |
| `Passwordless`  | Verify code and sign in    | `PasswordlessUserInputForm`                                                            | `PASSWORDLESS_CONSUME_CODE` | `consumeCodePOST`                |

To limit which actions require additional validation, pass additional configuration parameters to the frontend and backend setup steps.

#### Frontend conditional validation

On the frontend create a custom component that conditionally loads the CAPTCHA provider based on the name of the form. 

```tsx
import { forwardRef, useEffect } from "react";
import type { ComponentPropsWithoutRef } from "react";
import SuperTokens from "supertokens-auth-react";
import CaptchaPlugin, { useCaptcha, useCaptchaInputContainer } from "@supertokens-plugins/captcha-react";

type CaptchaInputContainerProps = ComponentPropsWithoutRef<ReturnType<typeof useCaptchaInputContainer>>;

const CaptchaInputContainer = forwardRef<HTMLDivElement, CaptchaInputContainerProps>((props, ref) => {
  const { form, ...rest } = props;
  const { load, render, containerId } = useCaptcha();

  useEffect(() => {
    // CAPTCHA applies/renders only for the EmailPasswordSignUpForm
    // and the EmailPasswordResetPasswordEmail
    if (form === "EmailPasswordSignUpForm" || form === "EmailPasswordResetPasswordEmail") {
      void load().then(() => render());
    }
  }, [form, load, render]);

  return (
    <div
      ref={ref}
      id={typeof containerId === "string" ? containerId : undefined}
      className="CAPTCHA-container"
      {...rest}
    />
  );
});

SuperTokens.init({
  appInfo: {
    appName: "...",
    apiDomain: "...",
    websiteDomain: "...",
  },
  recipeList: [
    // your recipes
  ],
  experimental: {
    plugins: [
      CaptchaPlugin.init({
        type: "reCAPTCHAv3", // or "reCAPTCHAv2" or "turnstile"
        captcha: {
          sitekey: "your-site-key",
        },
        InputContainer: CaptchaInputContainer,
      }),
    ],
  },
});
```

#### Backend conditional validation

On the backend pass a custom validation function that tells the plugin which actions should require extra validation.

```typescript
import SuperTokens from "supertokens-node";
import CaptchaPlugin, { SuperTokensPluginCaptchaConfig } from "@supertokens-plugins/captcha-nodejs";

const shouldValidate: NonNullable<SuperTokensPluginCaptchaConfig["shouldValidate"]> = (api, input) => {
  // Only require CAPTCHA for sign up
  if (api === "signUpPOST") {
    return true;
  }

  // Check request headers for suspicious activity
  if (api === "signInPOST") {
    const userAgent = input.options.req.getHeaderValue("user-agent");
    return !userAgent || userAgent.includes("bot");
  }

  return false;
};

SuperTokens.init({
  supertokens: {
    connectionURI: "...",
  },
  appInfo: {
    appName: "...",
    apiDomain: "...",
  },
  recipeList: [
    // your recipes
  ],
  experimental: {
    plugins: [
      CaptchaPlugin.init({
        type: "reCAPTCHAv3", // or "reCAPTCHAv2" or "turnstile"
        captcha: {
          secretKey: "your-secret-key",
        },
        shouldValidate,
      }),
    ],
  },
});
```

## Next steps

Besides CAPTCHA validation you can also look into the **Attack Protection Suite** feature which provides prevention against suspicious authentication attempts.

<CardGroup cols={3}>
  <Card title="Attack Protection Suite" href="/additional-verification/attack-protection-suite/introduction">
Prevent suspicious authentication attempts.
</Card>

  <Card title="Multi-factor Authentication" href="/additional-verification/mfa/introduction">
Add multi-factor authentication to your authentication flows.
</Card>

  <Card title="Plugins Reference" href="/references/plugins/introduction">
General information on how plugins work.
</Card>
</CardGroup>
