Interstitial Challenge
How Centinel verifies uncertain visitors with a brief in-browser challenge before granting access.
Overview
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. It must deny the request when a redirect has no response_html. 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.
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.
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 replace this page with your own design from the dashboard.
When Centinel sets the _centinel cookie, it assigns Max-Age=86400 (24 hours). Centinel can reissue the cookie and refresh that value. The server-side session uses the organisation's session_expiry_seconds setting. The cached verdict uses separate cache-TTL controls.
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
┌──────────────────────────────────────────┐
│ Visitor requests yoursite.com/article │
└────────────────────┬─────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Your backend calls POST /validate │
│ with URL, IP, headers, _centinel cookie │
└────────────────────┬─────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Validator decides │
└─────┬───────────────┬───────────────┬────┘
│ │ │
allow block redirect (interstitial)
│ │ │
▼ ▼ ▼
┌───────────┐ ┌─────────────┐ ┌────────────────────┐
│ Serve │ │ Serve block │ │ Serve interstitial │
│ content │ │ page │ │ HTML │
└───────────┘ └─────────────┘ └─────────┬──────────┘
│
▼
┌──────────────────────────────────┐
│ Browser sets session cookie │
│ Runs Centinel challenge │
│ (no visitor interaction) │
└────────────────┬─────────────────┘
│
▼
┌──────────────────────────────────┐
│ Centinel records the result │
│ for that session │
└────────────────┬─────────────────┘
│
▼
┌──────────────────────────────────┐
│ Browser reloads the same URL, │
│ now carrying the proven session │
│ cookie │
└────────────────┬─────────────────┘
│
▼
┌──────────────────────────────────┐
│ /validate recognizes the cleared │
│ session — no re-challenge │
└──────────────────────────────────┘Walking through it:
The visitor requests a protected URL. Your backend calls POST /validate.
The validator cannot confidently allow or block from request data alone. For an interstitial, it returns decision: "redirect" with base64 HTML in response_html.
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.
The browser renders the interstitial and runs Centinel's challenge logic. The visitor does nothing.
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.
The script reloads the same URL. Centinel never returns a redirect target, and redirect_url is never populated. While the server-side session and cached verdict remain available, later validations reuse the verdict.
Session continuity
After the challenge clears, Centinel caches the verdict against the session. While the server-side session and cached verdict remain available, later validations reuse that verdict. If either item is missing or expired, Centinel can evaluate and challenge the visitor again. The session uses the organisation's session_expiry_seconds setting. The cached verdict uses separate cache-TTL controls.
An interstitial is only served when a session exists. A redirect with no session would be
unwinnable, so Centinel converts it to a block with the reason interstitial_no_session. That
usually means your backend dropped the cookies from an earlier response.
Abandoned interstitials
Nothing is blocked for abandoning an interstitial. A visitor who closes the tab can leave the session unverified. A later request can trigger another evaluation and challenge.
After a grace period, Centinel detects stale redirect sessions for analytics. It writes an analytics event with decision: "block" and redirect_abandoned. This is reporting data, not live-request enforcement.
What this gives you
When the server-side session and cached verdict remain available, cleared traffic moves through your site without another challenge. A slow cache write can cause an extra round trip. Clients that never run JavaScript cannot clear the challenge, so they continue to receive the interstitial instead of your content.
Centinel serves the HTML, runs the verification, and tracks the result. You decode response_html
and return it with the status and headers from the response. If you want a branded challenge page,
you can author your own in the dashboard and select it per policy rule. 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, so a rendering failure never becomes a way in.