Skip to content

Explainer

Cloudflare Turnstile Retry and Refresh-Expired Settings Explained

What Cloudflare Turnstile's retry, retry-interval, refresh-expired and refresh-timeout settings do, their defaults, and when to change them.

By 5 min readPublished

A Cloudflare Turnstile widget has four settings that decide what it does after something goes wrong: retry (auto by default, or never) retries a failed challenge by itself; retry-interval sets the wait between those retries, 8,000 ms by default and 900,000 ms at most; refresh-expired (auto by default, manual or never) decides what happens when the token expires after 300 seconds; and refresh-timeout (auto by default in Managed mode, manual or never) decides what happens when an interactive challenge is not completed in time. Each can be set as a data- attribute or as a turnstile.render option.

This explainer describes each one with Cloudflare’s wording, as checked on 1 October 2026, shows a widget that handles failure and expiry itself, and says what the settings mean for automated clients.

The four settings

turnstile.render option Data attribute Values Default What it controls
retry data-retry auto, never auto “Controls whether the widget should automatically retry to obtain a token”
retry-interval data-retry-interval milliseconds, up to 900,000 8,000 “the time between retry attempts”
refresh-expired data-refresh-expired auto, manual, never auto What happens when the token expires
refresh-timeout data-refresh-timeout auto, manual, never auto in Managed mode What happens when an interactive challenge times out

Cloudflare describes the values like this:

  • retry: auto “Automatically retries failed challenges. Auto retry provides better visitor experience by automatically recovering from temporary network issues or processing errors.”
  • retry: never “Disables automatic retry. This requires manual intervention and gives you full control over error handling.”
  • refresh-expired: auto refreshes expired tokens automatically; manual “gives visitors control but requires them to take action”; never leaves all refresh logic to your page.
  • refresh-timeout: auto “Automatically refreshes upon encountering an interactive timeout”; manual “Prompts the visitor to manually refresh”; never “Will show a timeout”.

The callbacks that go with them

Option Cloudflare’s description
callback “A JavaScript callback invoked upon success of the challenge”
error-callback “A JavaScript callback invoked when there is an error”
expired-callback “Invoked when the token expires and does not reset the widget”
timeout-callback “Invoked when the challenge presents an interactive challenge but was not solved within a given time”

And the widget’s methods: turnstile.reset(widgetId), “To reset the widget if the given widget timed out or expired”; turnstile.getResponse(widgetId) to read the current token; turnstile.isExpired(widgetId) to check it; and turnstile.remove(widgetId).

When to change the defaults

The defaults suit most forms: failures retry on their own, and a visitor who leaves a form open for more than five minutes gets a new token without noticing. Change them when your page needs control:

  • retry: never when you show your own error message and let the visitor try again, or when you log every failure before retrying. Pair it with error-callback.
  • A longer retry-interval when many failures in a row would only add load, such as on a page behind a slow network.
  • refresh-expired: manual when a silent refresh would surprise the visitor, for example if you disable the submit button while the widget works.
  • refresh-expired: never when your page manages tokens itself: it hears expired-callback and calls turnstile.reset() when it is ready.

Here is a widget, rendered explicitly (the script loaded with ?render=explicit), that shows its own error message, and refreshes an expired token only when the visitor submits:

const submit = document.querySelector("#signup button[type=submit]");
const message = document.querySelector("#signup .captcha-message");
const widgetId = turnstile.render("#signup .captcha", {
sitekey: "0x4AAAAAAAB1cD2eF3gH4iJ5",
action: "signup",
retry: "never",
"refresh-expired": "never",
callback: () => {
message.textContent = "";
submit.disabled = false;
},
"error-callback": (code) => {
submit.disabled = true;
message.textContent = `The security check failed (${code}). Press "Try again".`;
},
"expired-callback": () => {
submit.disabled = true;
message.textContent = "The security check expired. It will run again when you submit.";
},
});
document.querySelector("#signup .captcha-retry").addEventListener("click", () => {
turnstile.reset(widgetId);
});
document.querySelector("#signup").addEventListener("submit", (event) => {
if (turnstile.isExpired(widgetId) || !turnstile.getResponse(widgetId)) {
event.preventDefault();
turnstile.reset(widgetId);
}
});

The error codes your error-callback receives are listed in Cloudflare Turnstile error codes. Whatever the widget does, your server must still validate each token with siteverify: the settings above only change the page.

What the settings do not change

  • The token’s lifetime. “Tokens are single-use and expire after 300 seconds (five minutes).” refresh-expired: auto gets a new token; it never makes an old one last longer. See Cloudflare Turnstile token expiry.
  • Server-side checks. A retried or refreshed token is a new token, validated once like any other. A replayed one fails with timeout-or-duplicate.
  • The widget’s mode. Managed, Non-Interactive and Invisible are set on the widget in the Cloudflare dashboard; see Cloudflare Turnstile widget modes.

What they mean for automated clients

When your automation puts a token from a solving API into a page, the page’s widget settings still run around it:

  • Your token has its own 300 seconds. The widget does not know when it was issued, and its refresh settings do not extend it. Fill the field just before you submit.
  • Pages that gate the button on callbacks (as in the example above) need the callback called with your token, or the button stays disabled. Submit a Cloudflare Turnstile token shows how to find and call it.
  • A widget that keeps retrying in an automated browser, with retry: auto, can change the page while you work. Read the sitekey once, then write the token and submit in one step.

ZeroCaptcha returns a token for the page and sitekey you name, valid for 300 seconds and good for one submission; the Cloudflare Turnstile solver page shows the call in ten languages and tools.

Sources

The team that builds and runs the ZeroCaptcha API. Articles are drafted with AI tools, then checked against the API's code and the primary sources each one cites.

Questions

What does refresh-expired do in Cloudflare Turnstile?

It decides what the widget does when its token expires after 300 seconds: auto (the default) refreshes it automatically, manual asks the visitor to refresh, and never leaves all refresh logic to your page.

What is the default retry-interval of Cloudflare Turnstile?

8,000 milliseconds. It sets the time between automatic retries after a failed challenge, up to a maximum of 900,000 milliseconds, and only applies while retry is auto.

Does refresh-expired make a Cloudflare Turnstile token last longer?

No. Every token expires 300 seconds after it was generated and can be validated once. Refreshing gets the widget a new token; it never extends an old one.

Read next

This article is part of the Cloudflare Turnstile solver hub. Every task is charged only when a token is ready.

Get an API key