← Cloudflare Turnstile / turnstile / troubleshooting
Ошибки на стороне клиента
Иногда в работе Turnstile возникают проблемы, и тогда вызывается error-callback.
Проблемы бывают разными: от сетевых сбоев и несовместимости браузера до ошибок конфигурации и неудачного прохождения проверки.
Продуманная обработка ошибок даёт посетителям понятное объяснение происходящего, а приложению позволяет восстановиться после временных сбоев.
См. Коды ошибок, где описано, как устранять конкретные ошибки.
Обработка ошибок
error-callback для явного рендеринга виджетов и data-error-callback для неявной отрисовки задаёт функцию обратного вызова JavaScript, которая обрабатывает возможные ошибки.
Механизм callback даёт полный контроль над тем, как ошибки показываются посетителям, и позволяет реализовать собственные сценарии восстановления под нужды вашего приложения.
turnstile.render('#my-widget', {
sitekey: 'your-sitekey',
'error-callback': function(errorCode) {
console.error('Turnstile error occurred:', errorCode);
handleTurnstileError(errorCode);
return true; // Indicates we handled the error
}
});<div class="cf-turnstile"
data-sitekey="your-sitekey"
data-error-callback="onTurnstileError"></div>Указывать обработчик ошибок необязательно, но в рабочих приложениях это рекомендуется. Если обработчик не задан, при ошибке Turnstile выбросит исключение JavaScript, а это способно нарушить работу страницы и испортить впечатление пользователей. Обработчик ошибок позволяет перехватить такие исключения и обработать их.
Если функция обратного вызова для ошибок возвращает значение, отличное от falsy, Turnstile считает, что ошибка уже обработана, и не выполняет дополнительное логирование. Если она возвращает falsy-значение (в том числе undefined), Turnstile запишет в консоль JavaScript предупреждение с кодом ошибки: это удобно при отладке во время разработки.
Обратный вызов ошибки получает код ошибки первым параметром. Код имеет структурированный формат: первые три цифры обозначают семейство ошибок (например, проблемы конфигурации, сбои сети или неудачные проверки), а остальные цифры указывают на конкретную ошибку внутри этого семейства.
function handleTurnstileError(errorCode) {
const errorFamily = Math.floor(errorCode / 1000);
switch(errorFamily) {
case 100:
showMessage('Please refresh the page and try again.');
break;
case 110:
showMessage('Configuration error. Please contact support.');
break;
case 300:
case 600:
showMessage('Security check failed. Please try refreshing or using a different browser.');
break;
default:
showMessage('An unexpected error occurred. Please try again.');
}
}Повторная попытка
По умолчанию при возникновении проблемы Turnstile повторяет попытку автоматически. Так кратковременные сбои сети и временная недоступность сервиса устраняются без участия пользователя.
Автоматические повторные попытки полезны для мобильные посетители с нестабильным подключением, а также посетителей в сетях с периодическими перебоями.
Если повторные попытки тоже завершаются неудачно, обратный вызов ошибки может сработать несколько раз из-за одной и той же причины. Учитывайте это в коде обработки ошибок, чтобы не показывать одно и то же сообщение по нескольку раз и не выполнять одно и то же восстановительное действие повторно.
let retryCount = 0;
turnstile.render('#my-widget', {
sitekey: 'your-sitekey',
'error-callback': function(errorCode) {
retryCount++;
if (retryCount <= 2) {
console.log(`Turnstile retry attempt ${retryCount}`);
return false; // Let Turnstile handle the retry
} else {
showPersistentErrorMessage(errorCode);
return true; // We'll handle it from here
}
}
});Поведение при повторных попытках можно изменить, задав для retry значение never вместо стандартного auto. В этом случае Turnstile не будет повторять попытки автоматически, и вы сами решаете, когда и как выполнять восстановление. Если при проверке посетителя возникнет любая проблема или ошибка, виджет не станет повторять попытку и останется в соответствующем состоянии сбоя, пока вы не вмешаетесь вручную.
turnstile.render('#my-widget', {
sitekey: 'your-sitekey',
retry: 'never',
'error-callback': function(errorCode) {
// You control all retry logic
setTimeout(() => {
turnstile.reset('#my-widget');
}, 3000);
}
});Вы можете вызвать turnstile.reset() в соответствующем error-callback, чтобы запустить повторную попытку вручную. Такой подход удобен, когда нужна собственная логика повторов: экспоненциальная задержка, подтверждение от пользователя перед повтором или разные стратегии в зависимости от конкретной ошибки.
Интервал между повторными попытками Turnstile задаётся параметром retry-interval, что позволяет подобрать интервал повторных попыток под типичные сетевые условия ваших посетителей. Более длинный интервал лучше подходит посетителям с медленным или менее надёжным соединением, а короткие интервалы хорошо работают там, где связь обычно стабильна.
turnstile.render('#my-widget', {
sitekey: 'your-sitekey',
retry: 'auto',
'retry-interval': 8000, // Wait 8 seconds between retries
'error-callback': handleError
});Интерактивность
Если посетитель не проходит интерактивную проверку за разумное время, срабатывает функция обратного вызова по тайм-ауту. Такой механизм не позволяет проверке бесконечно оставаться в состоянии ожидания и даёт посетителю понять, что от него требуется действие.
Возьмём форму, на заполнение которой уходит несколько минут. Если виджет Turnstile размещён в такой форме и посетитель долго не проходит интерактивную проверку, она устаревает. Посетители сосредоточены на полях формы и не замечают проверку Turnstile, поэтому при отправке формы токен оказывается просроченным или недействительным.
В таких случаях timeout-callback виджета срабатывает, и виджет может сбросить себя и показать посетителю нужные указания. Этот обратный вызов позволяет удобно обработать истечение времени: подсветить виджет Turnstile, показать уведомление или автоматически обновить проверку.
turnstile.render('#my-widget', {
sitekey: 'your-sitekey',
callback: function(token) {
console.log('Challenge completed successfully');
},
'timeout-callback': function() {
console.log('Challenge timed out - user action required');
document.getElementById('challenge-notice').textContent =
'Please complete the security check above to continue.';
// Optionally highlight the widget
document.getElementById('my-widget').style.border = '2px solid orange';
},
'expired-callback': function() {
console.log('Token expired - challenge needs refresh');
document.getElementById('challenge-notice').textContent =
'Security check expired. Please try again.';
}
});