How do you integrate hCaptcha with React Native?#
Install the official hCaptcha React Native package and its react-native-webview peer dependency, then render either the modal component or the inline component with your public sitekey. This guide covers both cases: the modal fits a submit action, while the inline component keeps the challenge inside your screen. In either case, send the returned token to your backend and accept the protected request only after hCaptcha Siteverify returns success: true.
Install the required react-native-webview peer dependency and test the integration with the application's exact React Native or Expo release and native toolchains.
Keep React Native verification focused on the user#
- Make visual tasks less frequent. hCaptcha Pro's 99.9% Passive mode reduces challenges in your modal or inline flow, helping users stay focused on completing the protected app action.
- Carry your app's design into verification. Pro's custom themes let you match challenge colors and styles to your React Native interface. The SDK accepts a custom theme for the verification experience.
New Pro sitekeys use 99.9% Passive by default. For an existing sitekey upgraded to Pro, select that mode under Behavior in the hCaptcha dashboard.
Before you start#
These instructions were last validated on September 22, 2026 with React Native SDK 4.1.0.
You need:
- A React Native app with iOS or Android configured.
- A backend endpoint for the action being protected.
- An hCaptcha account with a sitekey and matching secret.
- A secure backend secret store and outbound HTTPS access to hCaptcha.
Review the official React Native repository, npm package, and hCaptcha mobile SDK and integration catalog entries. The integrations-list repository records the broader catalog.
Create your hCaptcha credentials#
- Start with hCaptcha Pro for fewer challenges and adaptive protection on protected React Native app actions, or use existing compatible hCaptcha credentials.
- Create a sitekey for the protected mobile flow.
- Put the public sitekey in app configuration.
- Store the matching secret only in protected backend configuration.
The sitekey can ship with the application. The secret cannot. Never place the secret in JavaScript, native source, app configuration bundled with the client, or the application package.
Install the React Native component#
Install release 4.1.0 and its required WebView peer dependency:
npm install @hcaptcha/react-native-hcaptcha@4.1.0 react-native-webview
For a bare React Native iOS project, install the native pods using the workflow for that project. The repository also lists libswiftWebKit.tbd and JavaScriptCore.framework as iOS requirements. Confirm both requirements against the current Xcode project during technical review.
Open hCaptcha in a modal#
The package's default export is ConfirmHcaptcha. Keep a ref to it, call show() when the user submits, and always provide onMessage:
import React, { useRef } from "react";
import { Button } from "react-native";
import ConfirmHcaptcha from "@hcaptcha/react-native-hcaptcha";
export function ProtectedAction() {
const captcha = useRef(null);
async function onMessage(event) {
const message = event.nativeEvent.data;
if (message === "open") {
return;
}
if (event.success) {
try {
await sendRequestToBackend({ hcaptchaToken: message });
event.markUsed?.();
captcha.current?.hide();
} catch {
event.reset?.();
showVerificationError("The request was not accepted. Try again.");
}
return;
}
if (message === "challenge-closed") {
captcha.current?.hide();
return;
}
showVerificationError(message);
}
return (
<>
<Button title="Continue" onPress={() => captcha.current?.show()} />
<ConfirmHcaptcha
ref={captcha}
siteKey="YOUR_SITEKEY"
baseUrl="https://app.example.com"
onMessage={onMessage}
/>
</>
);
}
The repository uses https://hcaptcha.com as its example baseUrl and says this value generally does not need to change. The package generates its hCaptcha SDK host identifier from the sitekey unless you explicitly pass the advanced host prop. show() runs hCaptcha, and a token message contains the token in event.nativeEvent.data. Handle the package's open lifecycle message before checking event.success: release 4.1.0 marks open as successful even though it is not a token. Call markUsed() after the backend accepts the protected request so the component does not later report its default 120-second expiration. If the backend rejects the request or cannot be reached, keep the modal available, reset the component, show an error, and require a fresh token. The hook clears the wrapper's local expiration timer; it does not extend the token's server-side validity.
Handle non-success messages deliberately. The component can report closure, expiration, script errors, and loading timeouts. A loading timeout is not terminal, so the app should allow the user to keep waiting or retry. Use event.reset() when the flow should begin again.
Render hCaptcha inline#
Use the named Hcaptcha export when the challenge belongs inside the screen instead of a modal:
import { Hcaptcha } from "@hcaptcha/react-native-hcaptcha";
<Hcaptcha
siteKey="YOUR_SITEKEY"
url="https://app.example.com"
size="normal"
onMessage={onMessage}
/>
The inline component uses url; the modal uses baseUrl. The same token handling and backend verification requirements apply to both. Inline mode leaves surrounding layout and visibility under the app's control.
Verify the token on your backend#
The backend must reject a missing token, then send a URL-encoded POST to https://api.hcaptcha.com/siteverify. Include the server-held secret and the React Native token as response. The remoteip parameter is optional. We recommend sending it for improved verification accuracy and Enterprise risk scores when the backend derives the visitor's IP address from a reviewed, trusted hosting or proxy configuration; otherwise omit it. Also send the expected sitekey, which we recommend to prevent a token issued for another sitekey from being redeemed for this flow. Continue only when the response contains success: true.
Follow the server-side verification documentation. A successful component event does not authorize the protected action by itself.
Test the complete React Native flow#
- Confirm the modal and inline variants render on the intended platforms.
- Confirm successful tokens work once and reused or expired tokens fail.
- Test challenge closure, script errors, slow networks, offline mode, and retries.
- Test backgrounding, navigation, repeated verification, and screen teardown.
- Confirm the app uses the intended sitekey and that the backend submits that expected
sitekeyto Siteverify. - Build and test the supported iOS and Android targets on physical devices.
- Test the exact React Native or Expo, WebView, Xcode, and Android toolchain versions.
Troubleshoot common React Native problems#
The component cannot load or complete a challenge
Confirm react-native-webview is installed and linked for the current project type. Check network access, the sitekey, and the hostname supplied through baseUrl or url.
The backend rejects a successful token
Verify that the app sends the exact token from event.nativeEvent.data, the backend uses the matching secret, and Siteverify receives a URL-encoded POST. Do not reuse tokens.
An expiration message appears after successful submission
Call event.markUsed() after the backend accepts the protected request, as in the modal example. The component's default local expiration window is 120 seconds. This only clears the wrapper's expiration message; Siteverify still enforces token validity and single use.
The iOS build fails after installation
Run the project's native dependency installation and verify the repository's listed libswiftWebKit.tbd and JavaScriptCore.framework requirements against the current Xcode target. Framework and build settings need project-level review.
Frequently asked questions#
Does this guide cover both modal and inline hCaptcha?
Yes. Use the default ConfirmHcaptcha export for a modal or the named Hcaptcha export for an inline challenge.
Is the React Native package official?
Yes. We maintain the repository and npm package and link the integration from our documentation.
Does the component verify tokens on the backend?
No. Your backend must send every token and the private secret to Siteverify before accepting the protected request.
Can the hCaptcha secret be stored in the React Native app?
No. Client bundles and application packages can be inspected. Keep the secret on the backend and expose only the sitekey to the app.
Does release 4.1.0 support every React Native or Expo version?
The package declares React and React Native as unrestricted peer dependencies, but that does not prove compatibility with every version. Test the exact framework, WebView, native architecture, and build-tool combination before release.
Sources and references
- hCaptcha custom themes hCaptcha
- hCaptcha Pro product overview hCaptcha
- Official React Native hCaptcha component hCaptcha
- hCaptcha mobile app SDKs hCaptcha
- hCaptcha integrations hCaptcha
- React Native hCaptcha package hCaptcha
- Verify the user response server-side hCaptcha
- hCaptcha integrations list source hCaptcha
- hCaptcha Pro hCaptcha