# Interstitial Challenge

> How Centinel verifies uncertain visitors with a brief in-browser challenge before granting access.

Source: https://docs.centinelanalytica.com/concepts/interstitial-challenge

## Overview

The interstitial is for traffic the validator cannot confidently allow or block from request data alone. It gives an uncertain visitor a way to prove that they are human.

When `/validate` returns `decision: "redirect"` with a Centinel interstitial, your backend must serve the returned HTML. If you use a platform integration, verify that it applies the validator's `status_code`, `headers`, and `cookies`. The page runs a challenge in the visitor's browser. If the visitor clears it, they can continue to the protected content. If not, the session remains unverified.

A `redirect` does not always mean an interstitial. A custom block page can also use that decision. Do not infer challenge intent from `decision` alone. Serve the response HTML and status that the validator returns.

On rare occasions a `redirect` arrives with no `response_html` at all, because rendering or session encryption failed. Deny those requests rather than passing them through: the validator picked that visitor for a challenge, so an allow hands them the protected content.

## What a visitor sees

By default, a blank page titled "Please wait" with nothing to read and nothing to do. The
challenge is entirely non-interactive: there is no CAPTCHA and no puzzle. When it finishes, the
browser reloads the same URL and your backend serves the real content. You can author your own
challenge page in the dashboard and select it per policy rule.

### If the challenge can't run

Two screens can appear. While the browser is retrying a failed upload, the visitor sees **Still
verifying** with a spinner and "We're having trouble reaching our servers. Retrying
automatically." After the retry budget is spent, or when session storage is unavailable, they see
**Still unable to verify** with "We couldn't verify your connection after several attempts. Please
refresh the page or try again in a few minutes." and a reference code for support.

There is no fallback for clients that never run JavaScript. They keep receiving the interstitial
with whatever status your backend applies, which is why serving it with a 200 is a mistake.

## End-to-end flow

```mermaid
sequenceDiagram
    participant B as Browser
    participant A as Your backend
    participant C as Centinel

    B->>A: GET protected page
    A->>C: POST /validate
    C-->>A: Serve interstitial
    A-->>B: Execute script
    B->>C: Send telemetry
    B->>A: Reload page in client
    A->>C: POST /validate
    C-->>A: Allow or block
    A-->>B: Enforce decision
```

1. The visitor requests a protected URL. Your backend calls `POST /validate`.

2. The validator cannot confidently allow or block from request data alone. For an interstitial, it returns `decision: "redirect"` with base64 HTML in `response_html`.

3. Your backend returns the decoded interstitial HTML with `status_code` as the HTTP status, which is 403 by default. Apply the returned `cookies` and `headers` as well. The `Content-Security-Policy` header carries the nonce the challenge script needs, so dropping it stops the challenge from running.

4. The browser renders the interstitial and runs Centinel's challenge logic. The visitor does nothing.

5. Centinel runs the full validation pipeline after completion. The signals and fatal signals determine the result. A failed upload or retry can leave the session unverified.

6. The script reloads the same URL. Centinel never returns a redirect target, and `redirect_url` is never populated.

## See also

* [Validation API](https://docs.centinelanalytica.com/api/validation.md): Where the \`redirect\` decision originates.
* [Wire the validation API](https://docs.centinelanalytica.com/install/validation.md): Backend handling for redirect (and other decisions).
* [Scripts](https://docs.centinelanalytica.com/install/scripts.md): The browser collector script and the signals it adds.
* [Preserve the Referrer](https://docs.centinelanalytica.com/install/preserve-referrer.md): Keep the original traffic source across the interstitial reload.
