Skip to content
Cloudflare Docs

Conditionally enforce Turnstile

Last reviewed: about 2 months ago

This tutorial explains how to conditionally enforce Turnstile based on the incoming request, such as a pre-shared secret in a header or a specific IP address.

Overview

You may have setups such as automation that cannot load or run the Turnstile challenge. Using HTMLRewriter, this tutorial will demonstrate how to conditionally handle the client-side widget and siteverify API when specific criteria are met.

Implementation

This tutorial will modify the existing Turnstile demo to conditionally remove the existing script and widget container elements.

src/index.mjs
export default {
async fetch(request) {
// ...
if (request.headers.get("x-bypass-turnstile") === "VerySecretValue") {
class RemoveHandler {
element(element) {
element.remove();
}
}
return new HTMLRewriter()
// Remove the script tag
.on(
'script[src="https://challenges.cloudflare.com/turnstile/v0/api.js"]',
new RemoveHandler(),
)
// Remove the container used in implicit rendering
.on(
'.cf-turnstile',
new RemoveHandler(),
)
// Remove the container used in explicit rendering
.on(
'#myWidget',
new RemoveHandler(),
)
.transform(body);
}
return new Response(body, {
headers: {
"Content-Type": "text/html",
},
});
},
};

Server-side integration

We will exit early in our validation if the same logic we used to remove the client-side elements is present.

src/index.mjs
async function handlePost(request) {
if (request.headers.get("x-bypass-turnstile") === "VerySecretValue") {
return new Response('Turnstile not enforced on this request')
}
// Proceed with validation as normal!
const body = await request.formData();
// Turnstile injects a token in "cf-turnstile-response".
const token = body.get('cf-turnstile-response');
const ip = request.headers.get('CF-Connecting-IP');
// ...
}

With these changes, Turnstile will not be enforced on requests with the header x-bypass-turnstile: VerySecretValue present.

Demonstration

After running npm run dev in the project folder, you can test the changes by running the following command:

Terminal window
curl -X POST http://localhost:8787/handler -H "x-bypass-turnstile: VerySecretValue"
Turnstile not enforced on this request