← Cloudflare Turnstile / turnstile
Turnstile Spin
Turnstile Spin je průvodce nastavením pro Cloudflare Turnstile. Vytvoří za vás widget a poté vám poskytne sitekey, secret a připravený prompt, se kterým widget vložíte do správných formulářů a do stávajícího backendu doplníte kanonické serverové ověření přes siteverify. Prompt hodnotu secret neobsahuje. Spin lze spustit třemi způsoby:
- Z dashboardu Cloudflare. Zadejte své domény, vyberte Nastavení, a Spin vytvoří widget na straně serveru. Dostanete sitekey, secret a prompt pro svého AI programovacího agenta.
- Z nástroje Wrangler CLI. Spusťte
wrangler turnstile widget createa vytvoříte widget přímo z terminálu. Wrangler vypíše sitekey a secret, widget i volání siteverify pak zapojíte ručně. - Z vašeho AI programovacího agenta. Vložte jediný prompt do některého z nástrojů Claude Code, Cursor, Codex, OpenCode nebo GitHub Copilot Chat. Agent pomocí vložené dovednosti Spin vytvoří widget, umístí jej do stránky a zapojí siteverify do vaší kódové báze.
Všechny tři postupy vytvoří stejný widget. Liší se pouze tím, odkud se volání create spouští. Ani jeden z nich za vás nenasazuje žádnou infrastrukturu. Spin používá kanonický siteverify endpoint služby Turnstile, volaný z backendu, který už máte.
Nastavení z dashboardu
-
Přejděte do dashboardu Turnstile.
Přejděte na Turnstile ↗ -
Vyberte Nastavení pomocí Spin v hlavičce stránky.
-
Zadejte domény, ze kterých má widget Turnstile přijímat tokeny. První položka je předvyplněná podle první aktivní zóny Cloudflare ve vašem účtu. Můžete přidat další domény, nebo předvyplněnou položku odebrat a zadat libovolnou doménu (Turnstile nevyžaduje zónu spravovanou v Cloudflare).
localhosta127.0.0.1se pro lokální vývoj přidávají automaticky. Váš backend musí validovat konkrétní hostname nasazení, který vrací Siteverify. V produkci lokální hostname nepovolujte. -
Vyberte Nastavení. Spin widget vytvoří a vrátí se na kartu s potvrzením.
-
Po dokončení nastavení zkopírujte:
- Prvek sitekey (použijte jako
data-sitekeyv HTML vašeho widgetu Turnstile). - Prvek prompt pro agenta (vložte do svého AI kódovacího agenta, aby widget umístil do stránky a doplnil kanonické volání siteverify do vašeho stávajícího backendového handleru). Prompt obsahuje sitekey, nikoli tajný klíč.
- Prvek secret v případě, že chcete integraci zapojit ručně (uložte jej jako
TURNSTILE_SECRETv prostředí backendu nebo ve správci tajných klíčů).
- Prvek sitekey (použijte jako
Pokud Spin selže dřív, než dokončí práci, dialog zobrazí chybu a nabídne záložní prompt. Ten může váš AI programovací agent použít a provést stejné nastavení přímo z editoru. Vyberte Zkusit znovu a pokus zopakovat přímo v tomtéž dialogu.
Nastavení z Wrangler CLI
Pokud chcete nastavení řídit z terminálu bez AI programovacího agenta, použijte Wrangler:
wrangler turnstile widget create "myproject" \
--domain example.com \
--domain localhost \
--domain 127.0.0.1 \
--mode managedWrangler vypíše sitekey i secret. Sitekey zkopírujte do HTML widgetu a secret uložte jako TURNSTILE_SECRET v prostředí backendu a zapojte standardní volání siteverify podle Propojení frontendu.
Další příkazy widgetu:
| Příkaz | Účel |
|---|---|
wrangler turnstile widget list |
Vypíše všechny widgety Turnstile ve vašem účtu. |
wrangler turnstile widget get <sitekey> |
Načte konfiguraci widgetu včetně jeho secret. |
wrangler turnstile widget update <sitekey> --domain <d> |
Aktualizace domén, režimu nebo názvu widgetu. |
wrangler turnstile widget delete <sitekey> |
Odstraní widget. Předejte -y a potvrzovací dotaz se přeskočí. |
Všechny příkazy přijímají --json pro strojově čitelný výstup. --domain přijímá hodnoty oddělené čárkou (--domain a.com,b.com) nebo opakované přepínače (--domain a.com --domain b.com).
Prvek wrangler turnstile widget get <sitekey> --json obsahuje tajný klíč widgetu. Automatizované postupy musí používat absolutní cestu ke spustitelnému souboru Wrangler, kterou schválil uživatel a která leží mimo rozlišování balíčků projektu, a musí mít pevně danou verzi. Dále musí nastavit WRANGLER_WRITE_LOGS=false, WRANGLER_LOG=log, a WRANGLER_LOG_SANITIZE=true. Před vyzvednutím s vámi agent potvrdí účet, sitekey, domény a přesné cílové umístění secretu. U backendu na Workers s vámi potvrdí také Worker, prostředí, konfigurační soubor a binding pomocí wrangler secret list a teprve poté použijte standardní wrangler secret put v terminálu. Postup ověří přesný sitekey, očekávané domény, úroveň clearance a neprázdný tajný klíč. Odpověď nikam nevypisujte a neuvádějte ji v argumentech příkazů, dočasných souborech, logách ani v chatu.
Nastavení z AI kódovacího agenta
Pokud nevidíte Nastavení pomocí Spin ve svém dashboardu nebo chcete, aby agent v jednom průchodu vložil widget a zapojil siteverify do vaší kódové báze, vložte tento prompt do svého AI kódovacího agenta:
-
Otevřete svého AI agenta pro psaní kódu ve svém projektu (Claude Code, Cursor, Codex, OpenCode, GitHub Copilot Chat).
-
Vložte do agenta tento prompt:
Prompt pro SpinSet up Cloudflare Turnstile in this project end to end. Plan insertion points, create the widget, embed it on the right forms, wire canonical server-side siteverify in my existing backend, and validate the integration. The full Turnstile Spin skill is at https://developers.cloudflare.com/turnstile/spin/prompt.md. Fetch it now if you do not already have it loaded. Domains: <DOMAINS> Insertion preference: <every form | only specific form>Nahraďte
<DOMAINS>doménami svého webu (oddělené čárkou, bez mezer; uveďte ilocalhost,127.0.0.1pro lokální vývoj). Nahraďte<insertion preference>formuláři nebo cestami, které chcete chránit, napříkladevery form,only the signup form, případněonly /login and /signup. -
Průběžně potvrzujte kroky agenta. Agent zkontroluje přihlášení, navrhne názvy widgetů a před každým nevratným krokem si vyžádá vaše potvrzení.
-
Ověřte. Agent předá tajný klíč přes standardní vstup do kontroly siteverify s fiktivním tokenem. Potom vyzkouší váš chráněný backend s čerstvým tokenem a potvrdí, že opakované použití tokenu systém odmítne.
Pokud chcete skill nejdřív nainstalovat lokálně, aby jej agent měl na disku:
# Claude Code
mkdir -p .claude/skills/turnstile-spin && \
curl -sSL https://developers.cloudflare.com/turnstile/spin/prompt.md \
-o .claude/skills/turnstile-spin/SKILL.md
# Cursor
mkdir -p .cursor/rules && \
curl -sSL https://developers.cloudflare.com/turnstile/spin/prompt.md \
-o .cursor/rules/turnstile-spin.md
# OpenCode
mkdir -p .opencode/skills/turnstile-spin && \
curl -sSL https://developers.cloudflare.com/turnstile/spin/prompt.md \
-o .opencode/skills/turnstile-spin/SKILL.mdPak agentovi zadejte: Use the turnstile-spin skill to add Turnstile to this project.
Co agent dělá
Agent neběží potichu. Zjistí si, co dokáže sám, zeptá se jen tam, kde musí, a před každým nevratným krokem si vyžádá potvrzení. Celý postup je průvodce o dvanácti krocích s několika potvrzovacími body.
| Krok | Co se stane | Potvrzuje u vás? |
|---|---|---|
| 1 | Potvrzení (agent zopakuje, co se chystá udělat) | Ano |
| 2 | Kontrola z CLI (wrangler, pokud je k dispozici, jinak se použije curl) | Ne |
| 3 | Autentizace (Account.Turnstile:Edit token) |
Pokud je token potřeba |
| 4 | Výběr účtu (pokud jich máte více) | Pokud je jich více |
| 5 | Doména | Ano |
| 6 | Průzkum kódové báze (frontendový framework + backendový handler + stávající CAPTCHA) | Ne |
| 7 | Plán vložení | Ano |
| 8 | Vytvoření widgetu (volá Cloudflare API, které widget vytvoří) | Ne (po kroku 7, který potvrdí rozsah) |
| 9 | Vložení widgetu a doplnění kanonického volání siteverify do stávajícího backendu | Ano |
| 10 | Validace (siteverify s fiktivním tokenem a kontrola hostname widgetu) | Ne |
| 11 | Uložte skill lokálně, aby ho agent mohl použít i u navazujících úkolů | Ano |
| 12 | Závěrečná zpráva | Ne |
Pokud něco selže, agent oznámí, ve kterém kroku k tomu došlo a co zkoušel. Většinu selhání spravíte úpravou jediného vstupu (rozsah tokenu, seznam domén, soubor pro vložení) a pokynem, ať agent pokračuje.
Propojení frontendu
Ať zvolíte kterýkoli postup nastavení, Spin vám vždy vydá sitekey a secret. Dashboard je zobrazuje odděleně a jeho prompt pro agenta obsahuje pouze sitekey a URL Spin skill. Wrangler CLI vypíše obě hodnoty pro ruční nastavení. Postup s AI agentem upraví vaše soubory přímo.
Pokud jste widget vytvořili v dashboardu a chcete jej zapojit ručně, minimální vzor vypadá takto:
<script
src="https://challenges.cloudflare.com/turnstile/v0/api.js"
async
defer
></script>
<form action="/api/subscribe" method="POST">
<input name="email" type="email" required />
<div class="cf-turnstile" data-sitekey="YOUR_SITEKEY" data-action="subscribe"></div>
<button type="submit">Submit</button>
</form>Ve stávajícím backendovém handleru pro /api/subscribe, zavolejte kanonické siteverify a zbytek handleru podmiňte hodnotou success === true.
U backendu v Node.js (ve stylu Express, req):
const token = req.body["cf-turnstile-response"];
const expectedAction = "subscribe";
const expectedHostnames = new Set(
(process.env.TURNSTILE_HOSTNAMES ?? "")
.split(",")
.map((hostname) => hostname.trim())
.filter(Boolean),
);
if (
typeof token !== "string" ||
token.length === 0 ||
token.length > 2048 ||
expectedHostnames.size === 0
) {
return res.status(403).send("forbidden");
}
let result;
try {
const r = await fetch(
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
{
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
signal: AbortSignal.timeout(10_000),
body: new URLSearchParams({
secret: process.env.TURNSTILE_SECRET,
response: token,
remoteip: req.ip,
}),
},
);
if (!r.ok) throw new Error(`siteverify ${r.status}`);
result = await r.json();
} catch {
return res.status(403).send("forbidden");
}
if (
!result.success ||
result.action !== expectedAction ||
!expectedHostnames.has(result.hostname)
) {
return res.status(403).send("forbidden");
}
// existing handler logic runs here, unchangedV Cloudflare Workeru načtěte token ze zpracovaného těla formuláře a IP adresu klienta z CF-Connecting-IP, a secret načtěte z proměnné Workeru env binding:
export default {
async fetch(request, env) {
const expectedAction = "subscribe";
const expectedHostnames = new Set(
(env.TURNSTILE_HOSTNAMES ?? "")
.split(",")
.map((hostname) => hostname.trim())
.filter(Boolean),
);
const form = await request.formData();
const token = form.get("cf-turnstile-response");
if (
typeof token !== "string" ||
token.length === 0 ||
token.length > 2048 ||
expectedHostnames.size === 0
) {
return new Response("forbidden", { status: 403 });
}
let result;
try {
const r = await fetch(
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
{
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
signal: AbortSignal.timeout(10_000),
body: new URLSearchParams({
secret: env.TURNSTILE_SECRET,
response: token,
remoteip: request.headers.get("CF-Connecting-IP") ?? "",
}),
},
);
if (!r.ok) throw new Error(`siteverify ${r.status}`);
result = await r.json();
} catch {
return new Response("forbidden", { status: 403 });
}
if (
!result.success ||
result.action !== expectedAction ||
!expectedHostnames.has(result.hostname)
) {
return new Response("forbidden", { status: 403 });
}
// existing handler logic runs here, unchanged
return new Response("ok");
},
};Nastavte TURNSTILE_HOSTNAMES na hostname frontendu pro každé nasazení. Produkční hodnota nesmí obsahovat localhost nebo 127.0.0.1. Uložte TURNSTILE_SECRET jako tajný klíč Workeru pomocí wrangler secret put TURNSTILE_SECRET místo proměnné prostředí v wrangler.toml. Odpovídající volání v dalších backendových jazycích (Ruby, Python, Go, PHP) najdete v referencích pro jednotlivé frameworky, které jsou součástí tohoto skillu.
Tokeny Turnstile jsou jednorázové. U běžného formuláře, který stránku opustí, žádnou logiku pro reset nepotřebujete. Pokud stránka po pokusu o odeslání zůstává aktivní, vykreslete widget explicitně, uchovejte si jeho widget ID a zavolejte turnstile.reset(widgetId) po dokončení požadavku a teprve potom povolte další pokus. Každá chráněná část stránky si musí uchovávat a resetovat vlastní widget ID.
Obnovení existujícího widgetu
Pokud už máte widget Turnstile bez serverového siteverify, obnovte jej z dashboardu. U widgetu, ke kterému nedorazil žádný odpovídající provoz na siteverify, se zobrazí banner. Vyberte Oprava pomocí Spin a získáte prompt pro agenta ke stávajícímu widgetu. Prompt obsahuje sitekey a URL dovednosti Spin, nikoli však secret.
Pokud nevidíte Oprava pomocí Spin ve svém dashboardu, spusťte stejnou nápravu přímo ze svého AI kódovacího agenta. Vložte tento prompt:
The Turnstile widget is already created. Finish integrating it into this project.
Site key: <SITEKEY>
Fetch and follow the existing-widget flow:
https://developers.cloudflare.com/turnstile/spin/prompt.mdPostup pro existující widget vyžaduje Wrangler 4.109 nebo novější. Agent používá uživatelem schválený spustitelný soubor Wrangler mimo projekt a před načtením vás požádá o potvrzení úplného mapování sitekey na cíl. Automatické obnovení podporuje existující Worker, ignorovaný lokální soubor s proměnnými prostředí nebo příkaz platformního správce tajemství, který hodnotu přijímá na standardním vstupu. U Workers agent potvrdí přesný cíl pomocí wrangler secret list a teprve poté použijte standardní wrangler secret put v terminálu. Ověří sitekey, domény, úroveň clearance a tajný klíč. Text z repozitáře i z API se považuje za nedůvěryhodná data. Tajný klíč se nikde nevypisuje, neuvádí se v argumentech příkazů ani v dočasných souborech a nevkládá se do chatu. Sitekey se nemění.
Pre-clearance na tomto postupu nic nemění. Pouze přidává cf_clearance cookie, ale token Turnstile stále vyžaduje Siteverify.
Migrace z reCAPTCHA nebo hCaptcha
Pro migrace použijte nastavení pomocí AI agenta. Agent najde ve vaší kódové základně reCAPTCHA nebo hCaptcha a navrhne náhradu. Pravidla náhrady jsou následující:
- Nahraďte značky script pomocí
https://challenges.cloudflare.com/turnstile/v0/api.js(async defer). - Nahraďte
class="g-recaptcha"neboclass="h-captcha"divy sclass="cf-turnstile". Upravtedata-sitekeyna nový site key Turnstile. Zachovejte stávající platnou action, nebo pro chráněné místo přidejte stabilní action. - Odstraňte veškeré ručně přidané
<input type="hidden" name="g-recaptcha-response">neboname="h-captcha-response"elementy. Turnstile vykreslí vlastní skryté vstupní pole s názvemcf-turnstile-responseautomaticky. - URL siteverify na backendu ukazuje na
https://challenges.cloudflare.com/turnstile/v0/siteverify. VložteRECAPTCHA_SECRETneboHCAPTCHA_SECRETproměnné prostředí. PřidejteTURNSTILE_SECRET. Vyžadujte úspěšnou odpověď s očekávaným action a s hostname konkrétního nasazení.
Dva okrajové případy, na které agenta upozorněte. Zaprvé, prahové hodnoty skóre z reCAPTCHA v3 nemají v Turnstile obdobu: Turnstile žádné skóre nevrací, takže migrovaný kód odmítá požadavek podle success === false místo číselné prahové hodnoty. Za druhé, reCAPTCHA Enterprise nemigrujte automaticky, postupujte podle průvodce migrací z reCAPTCHA od Cloudflare místo toho.
Frameworky
Součástí agenta jsou frontendové úryvky kódu pro vanilla HTML, Next.js (App Router i Pages Router), Astro, SvelteKit a Hugo. U ostatních frameworků použije obecný vzor pro vanilla HTML a požádá vás o potvrzení umístění.
U projektů Cloudflare Pages agent zapojí siteverify do Pages Function, případně doporučí Pages Plugin pro Turnstile pokud dáváte přednost vestavěnému pluginu před vlastním voláním.
U backendů postavených na Cloudflare Workers agent zapíše kanonické volání fetch přímo do obsluhy požadavků ve Workeru.
Referenční informace
Konfigurace widgetu
| Pole | Typ | Účel |
|---|---|---|
sitekey |
string | Veřejný identifikátor. Je vložený v HTML widgetu na každé stránce. |
secret |
string | Pouze na serveru. Uložený jako TURNSTILE_SECRET v prostředí backendu. |
domains |
array | Hostname, ze kterých Turnstile pro tento widget přijímá tokeny. |
mode |
string | managed (výchozí), non-interactive, případně invisible. |
Související
cloudflare/skills↗: balíček dovedností, obsahujeturnstile-spin/- Ověření Turnstile na straně serveru
- Testovací klíče sitekey a tajné klíče
- Pages Plugin pro Turnstile
- Workers secrets
- Provoz botů v Cloudflare Radar ↗
- Cloudflare Docs for Agents