svelte-turnstile v0.9.0
Svelte Turnstile
Works with Svelte 3, 4, and 5 (compatibility mode)!
Cloudflare's Turnstile is a new CAPTCHA alternative, this library allows you to easily integrate it into your svelte projects.
Installing
npm install svelte-turnstile -D
Demo
https://svelte-turnstile.willow.codes
Using
The only required prop is the siteKey
which you can get from adding a site here.
<script>
import { Turnstile } from 'svelte-turnstile';
</script>
<Turnstile siteKey="SITE_KEY" />
Props
Prop | Type | Description | Required |
---|---|---|---|
siteKey | string | sitekey for your website | ✅ |
theme | 'light' \| 'dark' \| 'auto' | colour theme of the widget (defaults to auto ) | |
size | 'normal' \| 'flexible' \| 'invisible' \| 'compact' | size of the widget (defaults to normal ) | |
action | string | A string that can be used to differentiate widgets, returned on validation | |
cData | string | A string that can attach customer data to a challange, returned on validation | |
tabIndex | number | Used for accessibility (defaults to 0 ) | |
responseField | boolean | if true the response token will be a property on the form data (default true ) | |
responseFieldName | string | the name of the input which will appear on the form data (default cf-turnstile-response ) | |
retry | 'auto' \| 'never' | should the widget automatically retry to obtain a token if it did not succeed (default auto ) | |
retryInterval | number | if retry is true, this controls the time between attempts in milliseconds (default 8000 ) | |
language | SupportedLanguage \| 'auto' | the language turnstile should use (default auto ) | |
execution | 'render' \| 'execute' | controls when to obtain the token of the widget (default render ) | |
appearance | 'always' \| 'execute' \| 'interaction-only' | controls when the widget is visible. (default always ) |
For more information about some of the props and a list of SupportedLanguage
's checkout the Cloudflare Documentation.
Deprecated Props
forms
renamed toresponseField
formsField
renamed toresponseFieldName
Events
Event | Data | Description |
---|---|---|
callback | { token: string } | Emitted when a user passes a challenge |
error | { code: string } | Emitted when a user fails verification |
expired | {} | Emitted when a challenge expires and does not reset the widget |
timeout | {} | Emitted when a challenge expires and does reset the widget |
before-interactive | {} | Emitted before the challenge enters interactive mode |
after-interactive | {} | Emitted when the challenge has left interactive mode |
unsupported | {} | Emitted when a given client/browser is not supported |
Validate CAPTCHA
We need to validate the captcha token server side before we do any action on the server, this is to ensure no forgery occured. We can create a simple validate function:
If you are using a HTML Form and POSTing to a server you can get the cf-turnstile-response
(or what you configured it to using the responseFieldName
option) property to get the token
, otherwise you can use the on:callback
event in svelte to keep track of the token and send it to your backend.
interface TokenValidateResponse {
'error-codes': string[];
success: boolean;
action: string;
cdata: string;
}
async function validateToken(token: string, secret: string) {
const response = await fetch(
'https://challenges.cloudflare.com/turnstile/v0/siteverify',
{
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
response: token,
secret: secret,
}),
},
);
const data: TokenValidateResponse = await response.json();
return {
// Return the status
success: data.success,
// Return the first error if it exists
error: data['error-codes']?.length ? data['error-codes'][0] : null,
};
}
SvelteKit Example
In SvelteKit we can use form actions to easily setup a form with a captcha:
routes/login/+page.svelte
<script>
import { Turnstile } from 'svelte-turnstile';
let { form } = $props();
</script>
{#if form?.error}
<p>{form?.error}</p>
{/if}
<form method="POST" action="/login">
<Turnstile siteKey="SITE_KEY" theme="dark" />
</form>
routes/login/+page.server.js
// Copy and paste the validateToken function from above here
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
const token = data.get('cf-turnstile-response'); // if you edited the formsField option change this
const SECRET_KEY = '...'; // you should use $env module for secrets
const { success, error } = await validateToken(token, SECRET_KEY);
if (!success)
return {
error: error || 'Invalid CAPTCHA',
};
// do something, the captcha is valid!
},
};
Resetting
If you need to manually reset the widget, you can do so by binding to the reset
prop. For example:
<script lang="ts">
let reset = $state<() => void>();
</script>
<button onclick={() => reset?.()}> Reset </button>
<Turnstile bind:reset />
Support
Notable Changes
Full Changelog: https://github.com/ghostdevv/svelte-turnstile/releases
- Deprecate
forms
prop in favour ofresponseField
- Deprecate
formsField
prop in favour ofresponseFieldName
- Deprecate the
on:turnstile-callback
event in favour ofon:callback
- Deprecate the
on:turnstile-error
event in favour ofon:error
- Deprecate the
on:turnstile-timeout
event in favour ofon:timeout
- Deprecate the
on:turnstile-expired
event in favour ofon:expired
8 months ago
11 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago