---
title: "Migrating from Turnstile"
description: "Move from Cloudflare Turnstile to Edge Shield. It uses the same siteverify response shape and sitekey/secret model, so most migrations are a URL swap."
url: "https://edge.network/docs/shield/turnstile-migration"
section: "Shield"
---

# Migrating from Turnstile

Shield was designed to be a drop-in replacement: the same sitekey/secret model, and a siteverify response that matches Turnstile's field for field. Most migrations are a URL swap and a pair of new keys.

## 1. Create a Shield widget

In the [console](/console/shield), create a widget matching your Turnstile configuration: the same hostnames and the equivalent mode (Turnstile's Managed/Non-Interactive/Invisible map one-to-one to Shield's). Note your new sitekey and secret.

## 2. Swap the client snippet

```html
<!-- Before: Turnstile -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer></script>
<div class="cf-turnstile" data-sitekey="0x4AAA..."></div>
```

```html
<!-- After: Shield -->
<script src="https://shield.edge.network/api.js" defer></script>
<div class="edge-shield" data-sitekey="es_..." data-compat="turnstile"></div>
```

> [!NOTE]
> **Compatibility mode.** `data-compat="turnstile"` makes the widget also populate a `cf-turnstile-response` hidden input, so server code that reads Turnstile's field name keeps working without changes during the transition.

Shield's callbacks (`data-callback`, `data-error-callback`, `data-expired-callback`) follow the same conventions as Turnstile's.

## 3. Swap the siteverify URL and secret

```js
// Before
const url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'

// After: the response shape is identical (plus a "score" field)
const url = 'https://shield.edge.network/siteverify'
```

Replace the secret with your `es_secret_…` key. The response contains the same fields (`success`, `challenge_ts`, `hostname`, `error-codes`) with familiar error code names (`timeout-or-duplicate`, `invalid-input-secret`, etc.), so existing error handling carries over.

## 4. Optional: use the score

Turnstile gives you pass/fail. Shield's responses also carry a `score` (1–100). Once migrated, you can add graduated handling: auto-approve high scores, step up uncertain ones, and route or block automation. See [Server-side validation](/docs/shield/siteverify).

## Differences to be aware of

- **Key formats:** sitekeys are `es_…` and secrets `es_secret_…`. If you validate key formats anywhere, update the patterns.
- **Hidden input:** the default is `edge-shield-response`. Use `data-compat="turnstile"` during transition, then switch your server to the new field name at leisure.
- **Privacy:** Shield stores no per-visitor data and sets no cookies. If your privacy policy documented Turnstile's cookies, you can simplify it.
- **Idempotency:** like Turnstile, tokens are single-use and expire after 5 minutes.

## Next steps

- [Server-side validation](/docs/shield/siteverify) — Full API reference and error codes
- [Analytics](/docs/shield/analytics) — Watch your migrated traffic verify
