---
description: Validate Cloudflare Turnstile tokens in Pages Functions using the Turnstile Plugin.
title: Turnstile
image: https://developers.cloudflare.com/og-docs.png
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/pages/llms.txt  
> Use this file to discover all available pages before exploring further.

# Turnstile

Last updated Aug 24, 2026|Copy as Markdown|[View as Markdown](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/pages/functions/plugins/turnstile/index.md)|[Agent setup](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/agent-setup/)

[Turnstile](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/turnstile/) is Cloudflare's smart CAPTCHA alternative.

The Turnstile Pages Plugin validates Cloudflare Turnstile tokens.

## Installation

npmyarnpnpmbun

```
npm i @cloudflare/pages-plugin-turnstile
```

```
yarn add @cloudflare/pages-plugin-turnstile
```

```
pnpm add @cloudflare/pages-plugin-turnstile
```

```
bun add @cloudflare/pages-plugin-turnstile
```

## Usage

```typescript
import turnstilePlugin from "@cloudflare/pages-plugin-turnstile";

/**
 * POST /api/submit-with-plugin
 */

export const onRequestPost = [
	turnstilePlugin({
		// This is the demo secret key. In prod, we recommend you store
		// your secret key(s) safely.
		secret: "0x4AAAAAAASh4E5cwHGsTTePnwcPbnFru6Y",
	}),
	// Alternatively, this is how you can use a secret key which has been stored as an environment variable
	// (async (context) => {
	//   return turnstilePlugin({secret: context.env.SECRET_KEY})(context)
	// }),
	async (context) => {
		// Request has been validated as coming from a human
		const formData = await context.request.formData();
		// Additional solve metadata data is available at context.data.turnstile
		return new Response(
			`Successfully verified! ${JSON.stringify(context.data.turnstile)}`,
		);
	},
];
```

This Plugin only exposes a single route to verify an incoming Turnstile response in a `POST` as the `cf-turnstile-response` parameter. It will be available wherever it is mounted. In the example above, it is mounted in `functions/register.ts`. As a result, it will validate requests to `/register`.

## Properties

The Plugin is mounted with a single object parameter with the following properties:

[secret ↗](https://dash.cloudflare.com/login) is mandatory and can both be found in your Turnstile dashboard.

`response` and `remoteip` are optional strings. `response` is the Turnstile token to verify. If it is not provided, the plugin will default to extracting `cf-turnstile-response` value from a `multipart/form-data` request). `remoteip` is the requester's IP address. This defaults to the `CF-Connecting-IP` header of the request.

`onError` is an optional function which takes the Pages Function context object and returns a `Promise` of a `Response`. By default, it will return a human-readable error `Response`.

`context.data.turnstile` will be populated in subsequent Pages Functions (including for the `onError` function) with [the Turnstile Siteverify response object](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/turnstile/get-started/server-side-validation/).

Was this helpful?

YesNo

## On this page

[![](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/pages/functions/plugins/turnstile/#page","headline":"Turnstile · Cloudflare Pages docs","description":"Validate Cloudflare Turnstile tokens in Pages Functions using the Turnstile Plugin.","url":"https://developers.cloudflare.com/pages/functions/plugins/turnstile/","inLanguage":"en","image":"https://developers.cloudflare.com/og-docs.png","dateModified":"2026-08-24","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
