Jak zabezpieczyć formularz kontaktowy WordPress przed spamem
Formularz WordPress zasypany spamem? Poradnik: reCAPTCHA, honeypot, Turnstile, Akismet i inne metody antyspamowe. Porównanie rozwiązań i konfiguracja krok po kroku.

U nowego klienta pierwszym objawem, że coś jest nie tak, bywa jeden mail: „dostajemy po 200 wiadomości dziennie z formularza, większość to śmieci”. Logujemy się, patrzymy, zwykle widzimy to samo: Contact Form 7 z domyślną konfiguracją, reCAPTCHA v2 (checkbox „nie jestem robotem”), może Akismet z expired kluczem. Rozwiązanie zajmuje nam godzinę, ale zasady, które stosujemy — warto znać.
Honeypot pierwszy, zawsze
Najprostsza i najskuteczniejsza obrona przeciwko 90% botów — pole, którego nie widzi człowiek, ale bot wypełnia automatycznie.
<div style="position:absolute;left:-9999px;opacity:0" aria-hidden="true">
<label for="website">Nie wypełniaj tego pola</label>
<input type="text" name="website" id="website" tabindex="-1" autocomplete="off">
</div>Po stronie serwera: jeśli pole website ma wartość → odrzuć. Koszt: 0 zł, 0 impaktu na UX, nie wysyła danych do Google/Cloudflare, kompatybilne z RODO bez zgody użytkownika.
Efektywność: eliminuje większość dumb botów (te, które po prostu wypełniają wszystkie inputy). Nie zatrzyma inteligentnych (headless Chrome z custom skrypcją), dla nich potrzebne drugie zabezpieczenie.
W Contact Form 7 używamy Honeypot for Contact Form 7. WPForms ma to w pakiecie Pro. Fluent Forms — wbudowane.
Drugie zabezpieczenie: Cloudflare Turnstile (zamiast reCAPTCHA)
Od dwóch lat nie instalujemy u klientów reCAPTCHA. Powodów trzy:
- RODO. reCAPTCHA wysyła ciasteczka i fingerprint użytkownika do Google zanim kliknie formularz. Prawnicy RODO uważają to za transfer danych do USA bez wyraźnej zgody. Jeśli masz baner cookie „reCAPTCHA ładuje się dopiero po akceptacji” — OK. Większość stron go nie ma.
- UX. reCAPTCHA v2 to irytujące „zaznacz wszystkie mosty”. 20% użytkowników porzuca formularz.
- Koszt w LCP. reCAPTCHA ładuje ~100 KB JS przed interakcją.
Cloudflare Turnstile to free alternatywa, przezroczysta (żadnych challengy dla 99% userów), bez trackingu. Integracja w Contact Form 7 przez wtyczkę Simple Cloudflare Turnstile, w WPForms/Fluent Forms natywnie.
Konfiguracja w 5 minut:
- Zakładasz site w dash.cloudflare.com → Turnstile.
- Dostajesz site key i secret key.
- W wtyczce wklejasz oba klucze.
- Wybierasz tryb „Managed” (auto) lub „Invisible” (zupełnie niewidoczne).
Efektywność: ~95% botów filtrowanych bez interakcji użytkownika.
Akismet — dla content-level spam
Honeypot + Turnstile blokują 98% automatycznych botów. Reszta to często zwykły ludzki copy-paste („Promocja SEO tanie kliknięcia hit cena”) — wtedy zatrzymuje Akismet, który analizuje treść wiadomości i porównuje z globalną bazą spam.
Darmowy dla blogów osobistych, 9 $/mies dla firm. Plug in Contact Form 7 Akismet Integration robi resztę.
Uwaga compliance: Akismet też wysyła treść wiadomości do Automattic (USA). W politykach prywatności trzeba wymienić.
Rate limiting na poziomie Cloudflare
Jeśli serwis ma Cloudflare Pro (20 $/mies) albo Business, można dodać rule:
Jeśli path == /wp-admin/admin-ajax.php
AND requests na adres IP > 10 na minutęute
THEN challenge (CAPTCHA)Zatrzymuje ataki bruteforce na poziomie edge, zanim request dotrze do PHP. Darmowy Cloudflare tego nie ma, ale free plan ma „Security Level = High” który działa pseudorandomowo.
Dla ostrzejszego zastosowanie (sklep WooCommerce z checkout) — własny Worker, który liczy requesty na adres IP w KV i blokuje powyżej progu. U jednego klienta robiliśmy własny mechanizm ograniczający liczbę żądań, który po 5 próbach w 60s rzucał 429 Too Many Requests. Atak DDoS na checkout spadł z 40 tys. req/s do zera.
Czego nie instalujemy
- reCAPTCHA v2 checkbox — jak wyżej. UX katastrofa, RODO problem.
- reCAPTCHA Invisible — lepsze niż checkbox, ale wciąż ten sam problem z danymi do Google.
- Custom JS captchas („kliknij w czerwony kwadrat”) — dostępność (screen readery, klawiatura). Złe dla WCAG/EAA compliance.
- Math captchas („2 + 3 = ?”) — boty nauczyły się rozwiązywać. Użytkownicy nie nauczyli się ich lubić.
- Wtyczki “All-in-One spam” które robią wszystko naraz — zwykle robią wszystko źle. Wolimy 3 dedykowane wtyczki niż jedną „wszystko w jednym”.
Jak wygląda stack u klienta
Typowa konfiguracja dla formularza kontaktowego:
- Honeypot w samym formularzu (wtyczka lub kod w motywie).
- Cloudflare Turnstile jako widoczna ochrona (faktycznie niewidoczna dla 99% userów).
- Akismet dla content-level spam (tylko jeśli klient ma OK RODO).
- Rate limiting na poziomie Cloudflare (jeśli Pro).
- Log monitoring — raz na tydzień sprawdzamy logi wtyczki formularza. Podejrzane wzorce (ta sama treść z 20 IP) → dodajemy regułę do Cloudflare.
- Double opt-in dla formularzy zapisu na newsletter — brak spam’ów przez osoby trzecie (limit liczby żądań na same zapisy to inna sprawa).
Przy tym stacku spam w skrzynce spada z „setki dziennie” do „1–2 tygodniowo”. Całkowita eliminacja nie jest możliwa, bo 2% botów ma budżet na rozwiązywanie Turnstile’a ręcznie (tak, jest rynek Indonezji/Filipin gdzie ludzie rozwiązują captche za 2 $/godzinę). Dla tego ostatniego 2% — Akismet i manualne filtrowanie.
Konfiguracja Contact Form 7 step-by-step
CF7 jest stary, wolny, ładuje jQuery — nie polecamy na nowych stronach (wolimy WPForms Lite / Fluent Forms). Ale na legacy instalacjach CF7 można obronić:
[contact-form-7 id="123"]
Imię: [text* your-name]
Email: [email* your-email]
Wiadomość: [textarea your-message]
<!-- Honeypot -->
[honeypot honeypot-field]
<!-- Turnstile (po instalacji wtyczki) -->
[cfturnstile]
[submit "Wyślij"]
[/contact-form-7]W Dodatkowych ustawieniach:
acceptance_as_validation: on
demo_mode: offTestowanie
Po konfiguracji ZAWSZE test:
- Z innej przeglądarki / trybu incognito wyślij prawdziwy formularz — sprawdź, że trafia na skrzynkę.
- W DevTools → Network, wypełnij honeypot JS-em:
document.getElementById('website').value = 'bot'i wyślij. Powinien być odrzucony. - Wyłącz JavaScript i spróbuj wysłać — Turnstile powinien nie pozwolić (bo wymaga JS).
- Sprawdź, czy wiadomości nie trafiają do spamu maila — SPF/DKIM na domenie nadawcy + ewentualnie WP Mail SMTP z Postmarkiem/SendGridem.
Co gdy formularz jest ciągle zalany spamem
Jeśli mimo wszystkiego co wyżej spam dalej wchodzi, problem zwykle jest w:
- IP frendly country — boty z Polski/Niemiec mogą omijać część filtrów Cloudflare (jesteś w lokalnym regionie dla nich). W Cloudflare dodaj limit żądań na IP na minutęute.
- Formularz bez honeypota w motywie custom — wtyczki dodają CF7/WPForms, ale formularz w motywie nie ma. Trzeba dorzucić ręcznie.
- Stary endpoint — ktoś kiedyś miał
/kontakt-form.phpi zapomniał go usunąć. Skaner Patchstack to pokaże.
Gdy trafia do nas klient z „nie wiem co zrobić, dalej spam” — zaczynamy od audytu wszystkich aktywnych formularzy na stronie i sprawdzenia ich ustawień. Darmowy audyt obejmuje m.in. sprawdzenie ochrony formularzy.
Dobrze skonfigurowany formularz ma prosty cel: filtr 98% botów bez irytowania człowieka. Jeśli masz reCAPTCHA v2 i 200 spamów dziennie — to nie kwestia „dodania jeszcze jednej wtyczki”, to zmiana podejścia.

Doświadczony WordPress Developer z ponad 14-letnim stażem w tworzeniu zaawansowanych stron i sklepów internetowych. Specjalizuje się w WordPressie, dedykowanych wtyczkach i motywach.
Więcej o autorze

