React
React integration for NeoCaptcha.
Updated 2/22/2026
React Integration
Use this guide for React, Next.js, Vite, Remix, and similar frameworks.
Install
npm install @neocaptcha/sdk<NeoCaptcha> component
'use client';
import { useState } from 'react';
import { NeoCaptcha } from '@neocaptcha/sdk/react';
export default function SignupForm() {
const [token, setToken] = useState<string | null>(null);
return (
<form
onSubmit={async (e) => {
e.preventDefault();
if (!token) return;
await fetch('/api/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ captchaToken: token }),
});
}}
>
{/* other fields */}
<NeoCaptcha
siteKey={process.env.NEXT_PUBLIC_NEOCAPTCHA_SITE_KEY!}
onComplete={(verifyToken) => setToken(verifyToken)}
onError={() => setToken(null)}
onExpire={() => setToken(null)}
/>
<button type="submit" disabled={!token}>
Submit
</button>
</form>
);
}Props
| Prop | Type | Description |
|---|---|---|
siteKey | string | Required. Your site key. |
expiryTimeout | number | null | Optional. Token expiry in ms. |
onLoad | () => void | Widget iframe is ready. |
onComplete | (token: string) => void | User passed the challenge. |
onError | () => void | Error occcured. |
onExpire | () => void | Token expired. |
Next.js guidance
- Render the widget only in client components (
'use client'). - Use
NEXT_PUBLIC_NEOCAPTCHA_SITE_KEYfor the site key (public, safe for frontend). - Keep
NEOCAPTCHA_SITE_SECRETserver-only — never prefix it withNEXT_PUBLIC_. - Pass the token to API routes or server actions, then verify server-side.
Common mistakes
- Submitting a form before
tokenis set (beforeonCompletefires). - Treating a completed token as final trust without backend verification.