---
type: how-to
title: Customize the challenge
summary: Choose a game or a one-tap checkbox, pin the language and theme, and rename the cookie and callback path the gate uses on your origin.
---

The check page the gate shows is configured per site key, on its **Proxy gate** page in the dashboard, and through the [management API](/docs/automation/management-api), MCP, and Terraform like every other setting. Every option below defaults to the behaviour you already have, so a site key you never touch keeps working exactly as it did.

## Choose a game or a checkbox

**Challenge type** decides what the visitor actually does:

| Type | What the visitor does | When it fits |
|---|---|---|
| **Play a game** | Plays a short verification game in the page | Stronger signal against bots. The default. Costs the visitor a few seconds. |
| **Confirm with a checkbox** | Taps once while a proof-of-work check runs | Faster, lighter, no game to install. Weaker signal. |

Two rules constrain the choice:

- **A game-gated site key always shows a game.** If the site key's own **Require a game** setting is on, or your troop requires a game on every key, the checkbox option is unavailable and the dashboard says which setting is pinning it. Setting it through the API returns `409 gate-forces-game-mode`.
- **Choosing a game needs a game installed.** The site key needs at least one installed game with a replayable artifact, its own or inherited from the troop. Without one, *choosing* the game type returns `409 no-games`. Turning the gate on by itself does not: a site key that is not game-gated falls back to the checkbox, so the gate still works while you sort the games out.

<Callout type="info">
If the last installed game is later removed, a site key that requires a game stops serving the check rather than quietly falling back, because a checkbox cannot verify on a game-gated key. A key that does *not* require a game falls back to the checkbox so your site stays reachable.
</Callout>

That last case is worth knowing how to spot, because it takes a gated site offline: the gate answers every visitor with a "check unavailable" page until a game is available again. It can also arrive without anyone changing a setting, since a game only counts once its pinned version has passed our determinism check. The Proxy gate page warns whenever a site key is in that state and links to both the games list and the setting that is requiring a game, so you can either install one or lift the requirement and let the checkbox take over.

## Pin a language or a theme

Both **Language** and **Theme** default to *match the visitor*, which is almost always what you want:

- **Language** follows the visitor's own browser language, in the same eleven languages the widget supports.
- **Theme** follows the visitor's system light or dark preference, and switches with it.

Pin one instead when the gated site is single-language, or when it is committed to one theme and you want the check to match rather than follow the visitor's device.

Either way, the check page carries **this site key's branding**: the same brand name, logo, colours, and links your widget uses, resolved from the same site key. You configure that once, in your widget appearance settings, and the gate picks it up. Custom brand presets need the Apex plan, as they do for the widget; the language and theme options themselves work on every plan the gate is available on.

The check page's own wording is not customizable.

## Rename the cookie and the callback path

Change these only when the defaults clash with your app.

**Cookie name** (default `cpt_gate`) is the first-party cookie your proxy sets from the pass. Rename it if your app already uses that name, or if you run several gated apps on one domain and want them cleared independently.

<Callout type="warn">
**Renaming from one custom name to another takes your gated site offline until you copy the reverse-proxy snippet from your site key's Proxy gate page again and reload your proxy.** The gate looks for the new name while your proxy still writes the old one, so a visitor is sent to the check, passes it, and is sent straight back to it, in a loop that ends at a rate limit. Changing away from the default `cpt_gate` is safe to do first and wire up after, because the gate still recognises the default.
</Callout>

**The field POSTed to your callback is always `cpt_gate`**, whatever you name the cookie. So your callback's body parsing never changes; only the name it writes in `Set-Cookie` does. The response from the gate includes a `cookie_name` field telling your callback which name to use.

**Callback path** (default `/__cpt/callback`) is the route on your own origin that receives the pass and sets the cookie. Move it if your app's router already owns that path. It must be a plain path on your origin: no scheme, no host, no query string, no fragment.

## Scope the gate to some paths

**Gate only these paths** and **Never gate these paths** take one pattern per line and shape the generated reverse-proxy configuration. Leave both empty and every path is gated.

These are advisory: they change the snippet you copy, and your proxy is what enforces them. Always leave the authorizer subrequest and your callback path ungated, which the generated configuration does for you.

A typical login portal:

```
Gate only these paths:
/
/api/firstfactor

Never gate these paths:
/api/verify
/healthz
```

## See also

- [Set up the Proxy page-gate](/docs/proxy-page-gate/set-up) — the nginx walkthrough.
- [Reverse-proxy recipes](/docs/proxy-page-gate/reverse-proxy-recipes) — the callback contract and the other proxies.
- [Overview](/docs/proxy-page-gate/overview) — the concept and the clearance cookie.
