Overview
The@turnkey/core package supports Cloudflare Turnstile captcha protection to prevent automated abuse of authentication endpoints. When captcha is enabled in the Turnkey Dashboard, fresh captcha tokens are required for every Signup request and every InitOtp request.
Unlike @turnkey/react-wallet-kit, the core package does not include a built-in auth component or provider that handles captcha automatically. You are responsible for:
- Fetching your Turnstile site key from the Auth Proxy
- Rendering the Turnstile widget
- Passing captcha tokens to the appropriate SDK methods
Enabling Captcha in the Dashboard
Navigate to Wallet Kit settings
Go to the Turnkey Dashboard, navigate to the Wallet Kit page.
Fetching the Turnstile Site Key
Unlike the React Wallet Kit (which fetches this automatically), you need to manually retrieve the Turnstile site key from the Auth Proxy usinggetClientParams:
turnstileSiteKey is present in the response, captcha is enabled for your organization. If it is undefined, captcha is not enabled and no tokens are required.
You should call
getClientParams during your app’s initialization — alongside any other setup like client.init(). Cache the result so you don’t need to fetch it on every auth attempt.Installing the Turnstile Library
For web applications, we recommend using the Cloudflare Turnstile script directly, or a framework wrapper if you’re using React or another UI library.Vanilla JavaScript / script tag
Add the Turnstile script to your HTML:React (or other component frameworks)
If you’re using React with@turnkey/core directly, we recommend @marsidev/react-turnstile:
Integration
Turnstile Appearance
The Turnkey dashboard configures Turnstile in Managed mode, meaning Cloudflare decides whether a user needs to complete an interactive challenge. To keep the widget hidden unless interaction is required, useappearance: "interaction-only". This way most users will never see the captcha — it only appears when Cloudflare needs verification.
Vanilla JavaScript
Render the Turnstile widget and capture the token:React
Passing Captcha Tokens to SDK Methods
The following methods accept an optionalcaptchaToken parameter:
initOtpcompleteOtpsignUpWithPasskeysignUpWithOtpcompleteOauthloginOrSignupWithWallet
Token consumption pattern
Example: Email OTP flow
A complete OTP flow requires captcha tokens in two places — the initialinitOtp call and the completeOtp call. This means you need a fresh token for each step.
Example: Passkey signup
Example: Wallet login/signup
When captcha is not enabled (no
turnstileSiteKey from getClientParams), you can safely omit the captchaToken parameter — the requests will work as usual.Important Considerations
- Two tokens per OTP flow:
initOtpandcompleteOtpeach require their own captcha token. Make sure your UI resets the widget after the first token is consumed so a fresh token is ready for the second step. - Deploy first, enable second: Integrate captcha into your app before enabling it in the dashboard. The Turnstile widget will idle silently when no
turnstileSiteKeyis returned fromgetClientParams. - Handle expiration: Turnstile tokens expire after a short period. Listen for expiration events and clear your stored token to avoid submitting stale tokens.
- Reset after every use: Always reset the Turnstile widget after consuming a token so it can generate a new one.