turnstile-spin

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Turnstile Spin skill

Turnstile Spin 技能

Turns the prompt "set up Turnstile" into a working end-to-end integration: a widget, a deployed managed siteverify Worker, frontend snippets at every chosen insertion point, and a real validation pass before reporting success.
You are the agent. Run the wizard below by invoking the scripts under
scripts/
and branching on their JSON output. The scripts hold the deterministic logic (API calls, retry/error handling); your job is orchestration, codebase reading, confirmation, and the frontend edits.
Canonical instructions live at
developers.cloudflare.com/turnstile/spin
. If the docs page and this file disagree, trust the docs page.
将“设置Turnstile”的需求转化为可运行的端到端集成:一个小部件、一个已部署的托管siteverify Worker、在所有选定插入点的前端代码片段,以及在报告成功前的真实验证流程。
你是执行该任务的Agent。通过调用
scripts/
下的脚本并根据其JSON输出进行分支,来运行以下向导。脚本包含确定性逻辑(API调用、重试/错误处理);你的工作是编排流程、读取代码库、确认操作以及编辑前端代码。
标准说明位于
developers.cloudflare.com/turnstile/spin
。如果本文档与该页面内容不一致,以官方文档为准。

When to load this skill

何时加载此技能

Load when the user's prompt mentions any of:
  • "Turnstile", "CAPTCHA", "bot protection"
  • "siteverify", "cf-turnstile-response"
  • "protect this form", "stop bot signups", "spam signups"
  • A specific signup, login, or contact form combined with "Cloudflare" or "bot"
Do not load for unrelated Cloudflare tasks (Workers, Pages, R2, etc.) unless Turnstile is also mentioned.
当用户的提示包含以下任意内容时加载:
  • "Turnstile"、"CAPTCHA"、"bot protection"
  • "siteverify"、"cf-turnstile-response"
  • "protect this form"、"stop bot signups"、"spam signups"
  • 特定的注册、登录或联系表单,同时提及"Cloudflare"或"bot"
除非同时提到Turnstile,否则不要为无关的Cloudflare任务(Workers、Pages、R2等)加载此技能。

Conversation flow

对话流程

The user pasted the prompt. You are in a multi-step dialog. Detect what you can, ask only when you have to, confirm before every irreversible step. Each numbered moment is one agent message. Items marked [wait for user] require a user response.
  1. Brief acknowledge. One sentence: "I'll run Turnstile setup end to end. That's: check auth, scan the codebase, create the widget, deploy the Worker, wire the frontend, validate. Proceed?" [wait for user] Do NOT present a plan yet. Auth + scan come first.
  2. Wrangler check.
    npx wrangler --version
    . If missing, ask once: "Install wrangler with
    npm install --save-dev wrangler
    (Node project) or
    npm install -g wrangler
    (other)? Proceed?" [wait for user] If install is blocked entirely (corporate policy, blocked npm), fall back to driving Steps 4-5 via
    curl
    against
    api.cloudflare.com/client/v4/
    .
  3. Auth + scope probe (FIRST irreversible action). Run
    scripts/auth-probe.sh
    . Branch on
    status
    :
    • ok
      : continue to Step 4. The script already picked the account (single-account token, or one matching
      $CLOUDFLARE_ACCOUNT_ID
      ).
    • missing_token
      ,
      missing_scope
      , or
      missing_workers_scope
      : ask the user to create a token at https://dash.cloudflare.com/profile/api-tokens → Custom token → permissions
      Account.Turnstile:Edit
      and
      Account.Workers Scripts:Edit
      → include the target account in Account Resources. Do NOT direct them to
      wrangler login
      . Its OAuth scope doesn't include
      Account.Turnstile:Edit
      or
      Account.Workers Scripts:Edit
      . Offer three ways to hand the token over, cleanest first:
      1. Export + relaunch (token never enters chat):
        export CLOUDFLARE_API_TOKEN=<token>
        then restart the agent from that terminal.
      2. Save to file (token in file with user-only perms, not in chat):
        umask 077 && printf '%s' '<token>' > ~/.cf-turnstile-token
        , then read with
        TOKEN=$(cat ~/.cf-turnstile-token)
        .
      3. Paste in chat (fastest, but token lands in conversation log; user should rotate it after if the log is ever shared). If the user picks option 3 (paste in chat), you can use the wait to run Steps 5, 6, 7 (Domain, Codebase scan, Insertion plan). Options 1 and 2 will restart your session, so do not pre-fetch state in those cases. When auth is established, re-run
        auth-probe.sh
        , then continue to Step 8.
    • multiple_accounts
      : the token covers more than one account and
      $CLOUDFLARE_ACCOUNT_ID
      is unset. Present the numbered
      accounts
      list. [wait for user] Then export
      CLOUDFLARE_ACCOUNT_ID=<chosen>
      and re-run
      auth-probe.sh
      .
    • account_mismatch
      :
      $CLOUDFLARE_ACCOUNT_ID
      is set but isn't one of the token's accounts. Show the
      accounts
      list and ask the user to either
      unset CLOUDFLARE_ACCOUNT_ID
      or set it to one of those IDs.
  4. Account selection. If
    auth-probe.sh
    returned
    ok
    after a
    multiple_accounts
    round-trip, this is already done. Otherwise the script picked the single account silently and you continue to Step 5.
  5. Domain. Always include
    localhost
    and
    127.0.0.1
    . For production, scan
    package.json
    homepage
    ,
    wrangler.toml
    ,
    README.md
    ,
    AGENTS.md
    , git remote. Confirm: "I'll register for
    localhost
    ,
    127.0.0.1
    , and
    <domain>
    . OK?" [wait for user] If no production domain is found, ask.
  6. Codebase scan. Detect framework + insertion candidates silently.
  7. Insertion plan. Show the candidate list with
    [recommended]
    /
    [skip by default]
    markers; ask the user to confirm (numbers, "all", "recommended", or a list). [wait for user] If an existing CAPTCHA was detected, present a migration plan instead (see "Migrating from another CAPTCHA").
  8. Widget creation. Run
    scripts/widget-create.sh --account-id <id> --name <name> --domains <list> --mode managed
    . Report the sitekey. The secret stays in env; never write it to disk.
  9. Worker deploy. Run
    scripts/worker-deploy.sh --name turnstile-siteverify-<project-slug>
    with
    WIDGET_SECRET
    exported. Report the Worker URL on
    status: ok
    . On
    set_secret_failed
    , the Worker deployed but
    TURNSTILE_SECRET_KEY
    is not set on it; surface the error, then retry with
    echo "$WIDGET_SECRET" | npx wrangler secret put TURNSTILE_SECRET_KEY --name <returned worker_name>
    before running validation.
  10. Frontend edits. State the contract: "I'll add the widget + gate the existing submit handler on
    success === true
    . The existing handler logic stays the same." Ask "yes" / "show". [wait for user] If "show", print unified diffs and ask again. Do NOT propose alternate behavior (mail delivery, custom backends).
  11. Validation. Run
    scripts/validate.sh
    . Report each check as it passes. If any fails, surface the error and stop. [wait for user if anything fails]
  12. Persist skill. Ask: "Save the Spin skill to
    .claude/skills/turnstile-spin/SKILL.md
    so I can reuse it on follow-up tasks?" Default yes. [wait for user] Then run
    scripts/persist-skill.sh --path <agent-specific-path>
    .
  13. Final report. Print the structured summary: what was created, what was validated, what to do next.
用户已提交请求。你将进入多步骤对话流程。尽可能自动检测信息,仅在必要时提问,在执行每一个不可逆步骤前确认。每个编号环节对应一条Agent消息。标记为**[等待用户回复]**的项需要用户回应。
  1. 简要确认。用一句话说明:"我将端到端运行Turnstile设置流程,步骤包括:检查权限、扫描代码库、创建小部件、部署Worker、对接前端、验证。是否继续?" [等待用户回复] 此时不要展示详细计划,先执行权限检查和代码扫描。
  2. Wrangler检查。执行
    npx wrangler --version
    。如果未安装,询问一次:"是否安装wrangler?Node项目请用
    npm install --save-dev wrangler
    ,其他环境请用
    npm install -g wrangler
    ?是否继续?" [等待用户回复] 如果完全无法安装(如公司政策限制、npm被屏蔽),则改用
    curl
    调用
    api.cloudflare.com/client/v4/
    来完成步骤4-5。
  3. 权限验证与范围探测(第一个不可逆操作)。运行
    scripts/auth-probe.sh
    。根据
    status
    分支处理:
    • ok
      :继续步骤4。脚本已自动选择账户(单账户令牌,或匹配
      $CLOUDFLARE_ACCOUNT_ID
      的账户)。
    • missing_token
      missing_scope
      missing_workers_scope
      :请用户在https://dash.cloudflare.com/profile/api-tokens 创建自定义令牌,权限需包含
      Account.Turnstile:Edit
      Account.Workers Scripts:Edit
      ,并在账户资源中包含目标账户。不要引导用户使用
      wrangler login
      ,其OAuth权限不包含
      Account.Turnstile:Edit
      Account.Workers Scripts:Edit
      。提供三种安全的令牌提交方式,按优先级排序:
      1. 导出后重启(令牌不会进入聊天记录):执行
        export CLOUDFLARE_API_TOKEN=<token>
        ,然后从该终端重启Agent。
      2. 保存到文件(令牌存储在仅用户可访问的文件中,不会进入聊天记录):执行
        umask 077 && printf '%s' '<token>' > ~/.cf-turnstile-token
        ,之后通过
        TOKEN=$(cat ~/.cf-turnstile-token)
        读取。
      3. 粘贴到聊天框(最快,但令牌会进入对话日志;如果日志被分享,用户应在之后轮换令牌)。 如果用户选择选项3(粘贴到聊天框),你可以利用等待时间执行步骤5、6、7(域名确认、代码库扫描、插入计划)。选项1和2会重启会话,因此不要提前获取状态。权限验证通过后,重新运行
        auth-probe.sh
        ,然后继续步骤8。
    • multiple_accounts
      :令牌覆盖多个账户且
      $CLOUDFLARE_ACCOUNT_ID
      未设置。展示编号的
      accounts
      列表。[等待用户回复] 然后执行
      export CLOUDFLARE_ACCOUNT_ID=<chosen>
      并重新运行
      auth-probe.sh
    • account_mismatch
      $CLOUDFLARE_ACCOUNT_ID
      已设置,但不在令牌覆盖的账户范围内。展示
      accounts
      列表,询问用户是
      unset CLOUDFLARE_ACCOUNT_ID
      还是将其设置为列表中的某个ID。
  4. 账户选择。如果经过
    multiple_accounts
    流程后
    auth-probe.sh
    返回
    ok
    ,则此步骤已完成。否则脚本已自动选择唯一账户,直接继续步骤5。
  5. 域名确认。始终包含
    localhost
    127.0.0.1
    。对于生产环境,扫描
    package.json
    homepage
    wrangler.toml
    README.md
    AGENTS.md
    、git远程仓库。确认:"我将为
    localhost
    127.0.0.1
    <domain>
    注册。是否确认?" [等待用户回复] 如果未找到生产域名,询问用户。
  6. 代码库扫描。自动检测框架和候选插入点。
  7. 插入计划。展示候选列表,标记
    [推荐]
    /
    [默认跳过]
    ;请用户确认(可选择编号、"全部"、"推荐"或自定义列表)。[等待用户回复] 如果检测到已存在的CAPTCHA,则改为展示迁移计划(见"从其他CAPTCHA迁移")。
  8. 创建小部件。运行
    scripts/widget-create.sh --account-id <id> --name <name> --domains <list> --mode managed
    。报告sitekey。密钥仅保留在环境变量中;绝不要写入磁盘。
  9. 部署Worker。导出
    WIDGET_SECRET
    后运行
    scripts/worker-deploy.sh --name turnstile-siteverify-<project-slug>
    。当
    status: ok
    时报告Worker URL。如果
    set_secret_failed
    ,说明Worker已部署但未设置
    TURNSTILE_SECRET_KEY
    ;显示错误,然后通过
    echo "$WIDGET_SECRET" | npx wrangler secret put TURNSTILE_SECRET_KEY --name <returned worker_name>
    重试,之后再运行验证。
  10. 前端编辑。说明规则:"我将添加小部件,并在
    success === true
    时触发现有提交处理程序。现有处理程序逻辑保持不变。" 询问用户选择"确认" / "查看差异"。[等待用户回复] 如果选择"查看差异",打印统一差异并再次询问。不要提议替代方案(如邮件发送、自定义后端)。
  11. 验证。运行
    scripts/validate.sh
    。每通过一项检查就进行报告。如果任何检查失败,显示错误并停止。[如果失败则等待用户回复]
  12. 保存技能。询问:"是否将Spin技能保存到
    .claude/skills/turnstile-spin/SKILL.md
    ,以便后续任务复用?" 默认选择是。[等待用户回复] 然后运行
    scripts/persist-skill.sh --path <agent-specific-path>
  13. 最终报告。打印结构化摘要:已创建的内容、已验证的项以及下一步操作建议。

Things you must NOT do

绝对禁止的操作

  • Do not write the Turnstile secret to disk. Only pass it via stdin to
    wrangler secret put
    (the worker-deploy.sh script handles this).
  • Do not skip validation.
  • Do not overwrite files without showing a diff.
  • Do not deploy a Worker to a different account than the widget was created in.
  • Do not call siteverify from the browser. Always: browser → user's Worker → siteverify.
  • Do not use
    sudo
    or install global packages without asking.
  • 不要将Turnstile密钥写入磁盘。仅通过标准输入传递给
    wrangler secret put
    (worker-deploy.sh脚本会处理此操作)。
  • 不要跳过验证步骤。
  • 不要在未展示差异的情况下覆盖文件。
  • 不要将Worker部署到与小部件创建账户不同的账户。
  • 不要从浏览器调用siteverify。必须遵循:浏览器 → 用户的Worker → siteverify。
  • 不要使用
    sudo
    或未经询问就安装全局包。

Hard scope boundary: DO NOT ask the user about

严格范围边界:不要询问用户以下内容

Spin validates the Turnstile token via a managed Worker before the user's existing form handler runs. Everything else is out of scope:
  • Email / SMS / notification delivery. Leave the existing submit handler alone (just gate it on
    success === true
    ). Don't propose Resend, Mailchannels, SMTP, mailto.
  • Custom Worker code. Deploy the stock Worker template bundled at
    templates/worker/
    . Don't write a new Worker. Don't add features (rate limiting, custom routing, third-party integrations).
  • Database / payment / OAuth / form persistence. Out of scope.
  • Frontend framework migration, refactoring, or styling. Edit only what's needed.
  • reCAPTCHA v3 score thresholds. Turnstile returns
    success: true/false
    .
  • Pre-clearance-only setups. If
    clearance_level !== no_clearance
    , siteverify is optional and Spin doesn't apply. Redirect the user and exit.
Spin通过托管Worker在用户现有表单处理程序运行前验证Turnstile令牌。除此之外的所有内容均超出范围:
  • 邮件/SMS/通知发送。保留现有提交处理程序(仅在
    success === true
    时触发)。不要提议Resend、Mailchannels、SMTP、mailto等方案。
  • 自定义Worker代码。部署
    templates/worker/
    中的标准Worker模板。不要编写新的Worker,不要添加额外功能(如速率限制、自定义路由、第三方集成)。
  • 数据库/支付/OAuth/表单持久化。超出范围。
  • 前端框架迁移、重构或样式修改。仅编辑必要内容。
  • reCAPTCHA v3分数阈值。Turnstile仅返回
    success: true/false
  • 仅预授权设置。如果
    clearance_level !== no_clearance
    ,siteverify为可选操作,Spin不适用。引导用户查看相关文档并退出。

Recovery flow: respect existing widget configuration

恢复流程:兼容现有小部件配置

If the user tells you they already have a Turnstile widget set up and want to wire siteverify to it without rotating the sitekey (e.g. "I have a sitekey but siteverify never worked", "set up Spin against my existing widget
<sitekey>
"):
  1. Skip Step 8 (widget creation). The sitekey already exists; get it from the user.
  2. Fetch the widget metadata via
    scripts/fetch-secret.sh --account-id <id> --sitekey <key>
    . Branch on
    status
    :
    • ok
      : read
      secret
      ,
      clearance_level
      , and
      domains
      from the response. Confirm
      domains
      includes the user's production hostname; if not, surface the gap before proceeding.
    • missing_read_scope
      : tell the user to add
      Account.Turnstile:Read
      to the token, or fall back to asking them to paste the secret. In the paste path, you do not have
      clearance_level
      or
      domains
      ; ask the user to confirm both.
  3. Check
    clearance_level
    from the response (or the user's answer):
    • no_clearance
      : standard recovery (deploy Worker, wire siteverify).
    • anything else: ask whether they want siteverify on top of pre-clearance, or exit per the scope boundary.
  4. Continue from Step 9 (Worker deploy). Site key does not change. Dashboard's
    Deployment
    column flips from
    Manual
    to
    Spin
    on the first request carrying
    data-action="turnstile-spin-v1"
    .
  5. Never recreate the widget to get a fresh secret. That breaks the existing sitekey everywhere it's deployed.
如果用户告知已设置Turnstile小部件,希望对接siteverify但不更换sitekey(例如:"我有sitekey但siteverify无法工作"、"针对我现有的小部件
<sitekey>
设置Spin"):
  1. 跳过步骤8(创建小部件)。sitekey已存在,向用户获取。
  2. 通过
    scripts/fetch-secret.sh --account-id <id> --sitekey <key>
    获取小部件元数据。根据
    status
    分支处理:
    • ok
      :从响应中读取
      secret
      clearance_level
      domains
      。确认
      domains
      包含用户的生产主机名;如果不包含,在继续前告知用户。
    • missing_read_scope
      :告知用户为令牌添加
      Account.Turnstile:Read
      权限,或改为让用户粘贴密钥。如果用户选择粘贴密钥,你将无法获取
      clearance_level
      domains
      ,需询问用户确认这两项信息。
  3. 检查响应(或用户回答)中的
    clearance_level
    • no_clearance
      :执行标准恢复流程(部署Worker、对接siteverify)。
    • 其他值:询问用户是否要在预授权基础上添加siteverify,或根据范围边界退出。
  4. 从步骤9(部署Worker)继续。sitekey保持不变。当第一个携带
    data-action="turnstile-spin-v1"
    的请求发送后,控制台的
    Deployment
    列会从
    Manual
    变为
    Spin
  5. 绝不要重新创建小部件来获取新密钥。这会破坏所有已部署该sitekey的现有集成。

The frontend-edit contract

前端编辑规则

When wiring an existing form to the Worker (Step 10), the contract is: gate, don't replace. The user's existing submit handler keeps doing what it did. Spin only adds a validation step before it.
js
form.addEventListener("submit", async (e) => {
  e.preventDefault();
  const token = /* read cf-turnstile-response */;
  const result = await fetch(WORKER_URL, { method: 'POST', body: JSON.stringify({ token }) });
  const data = await result.json();
  if (!data.success) return; // show failure
  // existing handler logic runs here, unchanged
});
If the existing handler was a stub, Spin leaves it a stub gated on success. The user can replace the stub later; that's not Spin's job.
将现有表单对接Worker时(步骤10),规则是:拦截触发,而非替换。用户的现有提交处理程序保持原有功能。Spin仅在其之前添加验证步骤。
js
form.addEventListener("submit", async (e) => {
  e.preventDefault();
  const token = /* 读取cf-turnstile-response */;
  const result = await fetch(WORKER_URL, { method: 'POST', body: JSON.stringify({ token }) });
  const data = await result.json();
  if (!data.success) return; // 显示失败信息
  // 现有处理程序逻辑在此处运行,保持不变
});
如果现有处理程序是占位代码,Spin会将其保留为受验证拦截的占位代码。用户可在之后替换占位代码;这不属于Spin的职责范围。

Migrating from another CAPTCHA

从其他CAPTCHA迁移

During the Step 6 codebase scan, also look for existing reCAPTCHA or hCaptcha. If found, switch Step 7 to a migration plan.
Detection signals:
  • reCAPTCHA:
    https://www.google.com/recaptcha/api.js
    ,
    class="g-recaptcha"
    ,
    data-sitekey="6L..."
    , backend POST to
    /recaptcha/api/siteverify
  • hCaptcha:
    https://js.hcaptcha.com/1/api.js
    ,
    class="h-captcha"
    , backend POST to
    https://hcaptcha.com/siteverify
Substitution:
  • Replace script tags with
    https://challenges.cloudflare.com/turnstile/v0/api.js
    (
    async defer
    ).
  • Replace
    class="g-recaptcha"
    /
    class="h-captcha"
    divs with
    class="cf-turnstile"
    , update
    data-sitekey
    to the new Turnstile sitekey, add
    data-action="turnstile-spin-v1"
    .
  • Token field changes from
    g-recaptcha-response
    to
    cf-turnstile-response
    .
  • Backend siteverify URL points at the Spin-deployed Worker. Drop
    RECAPTCHA_SECRET
    /
    HCAPTCHA_SECRET
    env vars.
Edge cases to surface to the user:
  • reCAPTCHA v3 score thresholds. Turnstile has no score. Tell the user explicitly that migrated code will reject on
    success === false
    .
  • reCAPTCHA Enterprise. Don't auto-migrate. Point at developers.cloudflare.com/turnstile/migration/recaptcha/.
  • Custom
    action=
    values.
    Preserve any custom action the user passed to
    grecaptcha.execute
    as
    data-action
    on the widget. Use
    turnstile-spin-v1
    only when no custom action exists.
在步骤6的代码库扫描中,同时查找现有的reCAPTCHA或hCaptcha。如果找到,将步骤7切换为迁移计划。
检测信号:
  • reCAPTCHA:
    https://www.google.com/recaptcha/api.js
    class="g-recaptcha"
    data-sitekey="6L..."
    、后端POST请求到
    /recaptcha/api/siteverify
  • hCaptcha:
    https://js.hcaptcha.com/1/api.js
    class="h-captcha"
    、后端POST请求到
    https://hcaptcha.com/siteverify
替换规则:
  • 将脚本标签替换为
    https://challenges.cloudflare.com/turnstile/v0/api.js
    (保留
    async defer
    )。
  • class="g-recaptcha"
    /
    class="h-captcha"
    的div替换为
    class="cf-turnstile"
    ,将
    data-sitekey
    更新为新的Turnstile sitekey,添加
    data-action="turnstile-spin-v1"
  • 令牌字段从
    g-recaptcha-response
    改为
    cf-turnstile-response
  • 后端siteverify URL指向Spin部署的Worker。删除
    RECAPTCHA_SECRET
    /
    HCAPTCHA_SECRET
    环境变量。
需要告知用户的边缘情况:
  • reCAPTCHA v3分数阈值。Turnstile没有分数。明确告知用户迁移后的代码会在
    success === false
    时拒绝请求。
  • reCAPTCHA Enterprise。不要自动迁移。引导用户查看developers.cloudflare.com/turnstile/migration/recaptcha/
  • 自定义
    action=
    。保留用户传递给
    grecaptcha.execute
    的任何自定义action,将其作为小部件的
    data-action
    。仅当没有自定义action时才使用
    turnstile-spin-v1

Edge cases

边缘情况处理

SituationAction
wrangler
not installed
Install path:
npm install --save-dev wrangler
(Node project) or
npm install -g wrangler
(other)
Multiple Cloudflare accounts
scripts/auth-probe.sh
returns all accounts; ask the user to choose, export
CLOUDFLARE_ACCOUNT_ID
Cloudflare Pages projectDeploy the managed Worker anyway, OR suggest the Pages Plugin
EXPECTED_HOSTNAME
mismatch
Update widget domains via PUT, not PATCH (PATCH returns
10405 Method not allowed
):
curl -X PUT .../widgets/$SITEKEY -d '{"name":"...","mode":"managed","domains":[...]}'
Worker name conflict
worker-deploy.sh
retries automatically with a hash suffix
Token expired mid-flowStop, re-run
scripts/auth-probe.sh
, prompt for fresh credentials
Step 11 returns
missing-input-secret
Secret didn't propagate. Re-set:
echo "$WIDGET_SECRET" | npx wrangler secret put TURNSTILE_SECRET_KEY --name <worker_name from worker-deploy.sh output>
, wait 10s, re-validate. Use the
worker_name
field returned by
worker-deploy.sh
; do not rely on a
$WORKER_NAME
env var.
worker-deploy.sh
returns
set_secret_failed
Worker is deployed but secret is not set. Re-run only the secret-put using the returned
worker_name
:
echo "$WIDGET_SECRET" | npx wrangler secret put TURNSTILE_SECRET_KEY --name <worker_name>
. Surface the
detail
field to the user — it carries the wrangler error.
场景操作
wrangler
未安装
安装方式:Node项目用
npm install --save-dev wrangler
,其他环境用
npm install -g wrangler
多个Cloudflare账户
scripts/auth-probe.sh
返回所有账户;请用户选择,执行
export CLOUDFLARE_ACCOUNT_ID
Cloudflare Pages项目仍部署托管Worker,或建议使用Pages Plugin
EXPECTED_HOSTNAME
不匹配
通过PUT而非PATCH更新小部件域名(PATCH会返回
10405 Method not allowed
):
curl -X PUT .../widgets/$SITEKEY -d '{"name":"...","mode":"managed","domains":[...]}'
Worker名称冲突
worker-deploy.sh
会自动重试并添加哈希后缀
令牌在流程中过期停止流程,重新运行
scripts/auth-probe.sh
,提示用户提供新凭证
步骤11返回
missing-input-secret
密钥未同步。重新设置:
echo "$WIDGET_SECRET" | npx wrangler secret put TURNSTILE_SECRET_KEY --name <worker_name from worker-deploy.sh output>
,等待10秒后重新验证。使用
worker-deploy.sh
输出中的
worker_name
字段;不要依赖
$WORKER_NAME
环境变量。
worker-deploy.sh
返回
set_secret_failed
Worker已部署但未设置密钥。使用返回的
worker_name
重新执行密钥设置:
echo "$WIDGET_SECRET" | npx wrangler secret put TURNSTILE_SECRET_KEY --name <worker_name>
。将
detail
字段的错误信息展示给用户——该字段包含wrangler的错误详情。

Telemetry marker

遥测标记

Every snippet you write must include
data-action="turnstile-spin-v1"
. Account-level aggregate telemetry, never per-user. Cloudflare uses it to measure activation. If the user removes the attribute, the integration still works; only the analytics segmentation is lost.
你编写的所有代码片段必须包含
data-action="turnstile-spin-v1"
。这是账户级别的聚合遥测,不会收集用户个人信息。Cloudflare用它来衡量激活情况。如果用户移除该属性,集成仍可正常工作;仅会丢失分析细分数据。

Do not

禁止操作

  • Do not write the secret to disk.
  • Do not skip validation (Step 11).
  • Do not propose features outside the wizard (custom Worker code, custom domains, advanced WAF rules) unless asked.
  • Do not call siteverify from the browser.
  • Do not deploy the Worker into a different account than the widget.
  • 不要将密钥写入磁盘。
  • 不要跳过验证步骤(步骤11)。
  • 除非被询问,否则不要提议向导之外的功能(自定义Worker代码、自定义域名、高级WAF规则)。
  • 不要从浏览器调用siteverify。
  • 不要将Worker部署到与小部件创建账户不同的账户。