Налаштування 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 при успішній верифікації.
Режим невидимості
<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 не пройдена' });
}
// Обробка форми
});
Верифікація на стороні сервера (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 годин на повну інтеграцію з верифікацією на стороні сервера.







