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

# Bot protection

> Turn on the bot check that keeps automated submissions out of your forms.

allGood uses Cloudflare Turnstile to tell real visitors from bots. A widget is created once for your account, and it covers the domains you've connected.

**Where:** Settings → Web Edge (the **Bot protection** card) and Settings → Form Processing (the **Bot protection** dropdown).

<Tip>
  Configuring this for a marketer, not building against it? See [Turn on bot protection for a form](/mk/settings/web-edge/bot-protection) for the settings-only walkthrough.
</Tip>

## How it works

When a form requires a bot check:

1. The allGood script renders the widget on your page.
2. The visitor's browser produces a token, usually without them doing anything.
3. The token is sent with the submission.
4. allGood verifies it and refuses a missing or invalid one.

The widget's **sitekey** is public and ships in your page's HTML. Its secret never leaves allGood and can't be read from the app or the API.

## Provisioning it

There's no "create widget" button. Connect a domain, wait for it to reach **active**, then press **Sync** on Settings → Web Edge. The widget is created — or extended to cover the new hostname — as part of that sweep.

Until then the screen tells you so, and forms that require a bot check can't be registered.

<Frame caption="The Bot protection card, showing how many hosts the widget covers and the public sitekey.">
  <img src="https://mintcdn.com/allgoodtechnologyinc/bf1LRHwyriZvgDxT/images/mk/web-edge/setup-bot-protection-card.png?fit=max&auto=format&n=bf1LRHwyriZvgDxT&q=85&s=b4a1f3de92e2c754d3fd3061b17afcd6" alt="The Bot protection card, showing how many hosts the widget covers and the public sitekey" width="1105" height="163" data-path="images/mk/web-edge/setup-bot-protection-card.png" />
</Frame>

## Both switches have to agree

Bot protection is a two-sided decision.

| Side         | Where                                           | Effect                                                                                    |
| ------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Account-wide | Settings → Form Processing → **Bot protection** | Setting this to **None** cancels the bot check for every form, whatever the form asks for |
| Per form     | The form's own definition                       | Opts that one form in                                                                     |

A check runs only when both are on. Per-form opt-in is off by default.

## The failure worth knowing about

<Warning>
  A Turnstile widget only issues tokens on hostnames it covers. If a form requires a bot check and sits on a hostname the widget **doesn't** cover, the browser produces no token, and **every submission from that page is refused as a bot** — with nothing obviously wrong in your setup and a form that looks correctly configured.
</Warning>

Two places tell you before it bites:

* The coverage chip on each row of the [allowed origins](/mk/developer/web-edge/allowed-origins) list.
* The fourth step on a domain row, **Bot protection ready**.

The fix in both cases is the same: press **Sync** on Settings → Web Edge.

allGood also refuses to register a form that requires a bot check while no widget exists, precisely so you can't reach the silent version of this by accident.

## What the visitor sees

If you use the allGood script, the widget is placed just before your form's submit button and the Turnstile loader is fetched once per page. Style it with the `.cf-turnstile` class if you need to move it.

<Warning>
  If your site sets a Content Security Policy, it has to allow `https://challenges.cloudflare.com` for both `script-src` and `frame-src`. Otherwise the widget never renders — and again, every submission is refused.
</Warning>

If you build the request yourself, you render the widget yourself and send the token. See the [Form capture API](/mk/developer/web-edge/reference/form-api).

## Next

→ [Consent provider](/mk/developer/web-edge/consent-provider)
