Настройка Turnstile (Cloudflare) для защиты форм сайта
Cloudflare Turnstile — замена CAPTCHA, которая не показывает пользователю никаких задач. Анализирует сигналы браузера и поведение в фоне, выдаёт токен подтверждения без визуальных испытаний. Бесплатен, не требует подписки Cloudflare.
Преимущества перед reCAPTCHA/hCaptcha
- Нет визуальных задач вообще — в большинстве случаев просто появляется галочка за доли секунды
- Не отслеживает пользователей для целей рекламы
- Управляемые режимы: Managed, Non-Interactive, Invisible
- Работает без аккаунта Cloudflare для конечных пользователей
Регистрация
Ключи в Cloudflare Dashboard → Turnstile. Нужны site_key и secret_key. Для тестирования доступны специальные ключи (всегда проходят / всегда блокируют).
Базовая интеграция
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<form method="POST" action="/submit">
<input type="email" name="email" required>
<div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>
<button type="submit">Отправить</button>
</form>
Turnstile автоматически добавляет скрытое поле cf-turnstile-response при успешной верификации.
Invisible-режим
<div id="turnstile-widget"
class="cf-turnstile"
data-sitekey="YOUR_SITE_KEY"
data-size="invisible"
data-callback="onTurnstileSuccess">
</div>
<script>
function onTurnstileSuccess(token) {
document.getElementById('hidden-token').value = token;
document.getElementById('myForm').submit();
}
// Ручной вызов
turnstile.execute('#turnstile-widget');
</script>
Серверная верификация (Node.js/Express)
const verifyTurnstile = async (token, remoteip) => {
const response = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: process.env.TURNSTILE_SECRET,
response: token,
remoteip,
}),
});
const data = await response.json();
return data.success === true;
};
app.post('/contact', async (req, res) => {
const token = req.body['cf-turnstile-response'];
const valid = await verifyTurnstile(token, req.ip);
if (!valid) {
return res.status(422).json({ error: 'Turnstile verification failed' });
}
// Обработка формы
});
Серверная верификация (PHP/Laravel)
$token = $request->input('cf-turnstile-response');
$result = Http::post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
'secret' => config('services.turnstile.secret'),
'response' => $token,
'remoteip' => $request->ip(),
]);
if (!$result->json('success')) {
return back()->withErrors(['captcha' => 'Проверка не пройдена']);
}
React-интеграция
import { Turnstile } from '@marsidev/react-turnstile';
function ContactForm() {
const [token, setToken] = useState(null);
return (
<form onSubmit={handleSubmit}>
<Turnstile
siteKey={process.env.REACT_APP_TURNSTILE_SITE_KEY}
onSuccess={setToken}
onExpire={() => setToken(null)}
options={{ size: 'invisible' }}
/>
<button type="submit" disabled={!token}>
Отправить
</button>
</form>
);
}
Тестовые ключи
| Site Key | Поведение |
|---|---|
1x00000000000000000000AA |
Всегда проходит |
2x00000000000000000000AB |
Всегда блокирует |
3x00000000000000000000FF |
Всегда запрашивает вызов |
Срок реализации
3–6 часов на полную интеграцию с серверной верификацией.







