Enjoying react-native-turnstile?

Buy me a coffee
React NativeCloudflare Turnstile

Turnstile for React Native, without the WebView cookie headache.

A wrapper for Cloudflare Turnstile that loads a tiny hosted Next.js app and bridges the widget into react-native-webview.

Installsh
npm i react-native-turnstile react-native-webview

How it works

A hosted bridge for an incompatible cookie jar

The cookies used by Cloudflare Turnstile are incompatible with react-native-webview. This package circumvents that by loading a tiny Next.js app on Cloudflare that creates an interface between a WebView and the Turnstile widget.

Your React Native app

Render ReactNativeTurnstile and listen for verify, expire, error, and timeout events.

WebView bridge

The package loads this hosted site inside a WebView and posts Turnstile events back to native.

Turnstile widget

The challenge runs in a real browser context, then your app receives the token through onVerify.

Installation

Add the package and a WebView

Install react-native-turnstile plus react-native-webview. Expo projects should install the WebView package through Expo first.

npmsh
npm i react-native-turnstile react-native-webview
Exposh
expo install react-native-webview
npm i react-native-turnstile

Usage

Drop in the widget and handle the token

Pass your sitekey, handle onVerify, and optionally keep a reset ref for failed requests or expired tokens.

TurnstileWidget.tsxtsx
import { useRef } from "react";
import ReactNativeTurnstile, { resetTurnstile } from "react-native-turnstile";

const turnstileResetRef = useRef();

const result = await fetch("/path/to/some/api");
if (!result.ok) {
  resetTurnstile(turnstileResetRef);
  throw new Error(`Request failed with code ${result.status}`);
}

function TurnstileWidget() {
  return (
    <ReactNativeTurnstile
      sitekey="xxxxxxxxxxxxxxxxxxx"
      onVerify={token => console.log(token)}
      resetRef={turnstileResetRef}
      style={{ marginLeft: "auto", marginRight: "auto" }}
    />
  );
}

Turnstile tokens expire after 5 minutes. To automatically reset the challenge once they expire, set the autoResetOnExpire prop to true or reset the widget yourself using the onExpire callback.

Documentation

ReactNativeTurnstile props

These props map to the Turnstile widget configuration, except backgroundColor, which sets the hosted page background inside the WebView. For more details on what each argument does, see the Cloudflare documentation.

NameTypeDescription
sitekeyrequiredstringSitekey of your Turnstile widget.
actionstringOptional action name passed to Turnstile.
cDatastringOptional custom payload passed to Turnstile.
themestringOne of "light", "dark", or "auto".
sizestringOne of "compact" or "normal".
tabIndexnumberTab index for the widget.
responseFieldbooleanControls generation of the hidden input element.
responseFieldNamestringChanges the name of the hidden input element.
retrystringOne of "auto" or "never".
retryIntervalnumberInterval of retries in milliseconds.
autoResetOnExpirebooleanAutomatically reset the widget when the token expires.
idstringID of the widget container.
backgroundColorstringBackground color of the hosted Turnstile page. Any CSS color value (default `#ffffff`).
resetRefTurnstileResetRefRef used to inject a programmatic reset() call.
classNamestringProvided to facilitate NativeWind classes.
styleStyleProp<ViewStyle>Passed to the React Native View container.

Callbacks

NameArgumentsDescription
onVerifyrequiredtokenCalled when the challenge is passed.
onLoadwidgetIdCalled when the widget is loaded.
onErrorerrorCalled when an error occurs.
onExpiretokenCalled when the token expires.
onTimeoutCalled when the challenge expires.

Enjoying react-native-turnstile?

Buy me a coffee