Spamschutz
Honeypot, signierte Zeitstempel, Spam-Bewertung, eine Menschlichkeitsprüfung, erlaubte Domains und Rate-Limits.
Jedes Formular bekommt ohne Einrichtung mehrstufigen Schutz: einen Honeypot, einen signierten Render-Zeitstempel, Spam-Bewertung und Rate-Limits. Zusätzlich kannst du eine Menschlichkeitsprüfung hinzufügen und das Formular auf deine eigenen Domains beschränken.
| Ebene | Standardmäßig aktiv | Ergebnis |
|---|---|---|
| Rate-Limits | Ja, Preset Standard | 429 rate_limited |
| Erlaubte Domains | Nein | Spam oder 403 origin_not_allowed |
| Menschlichkeitsprüfung | Nein | 403 challenge_required oder eine Prüfseite |
| Honeypot | Ja | +5 auf die Bewertung |
| Spam-Bewertung | Ja | Spam ab 5 |
Wie Spam behandelt wird
Ein Post, der als Spam eingestuft wird, wird mit dem Status spam gespeichert und bekommt trotzdem eine normale Erfolgsantwort, damit Bots nichts lernen. Spam löst keine Webhooks und keine E-Mails aus, zählt nicht zu deiner monatlichen Nutzung und wird nach 30 Tagen gelöscht. Prüfe ihn im Dashboard oder mit der REST API; wenn du eine Einsendung als kein Spam markierst, werden dann ihre Webhooks gesendet.
Jeden Montag bekommt jeder Workspace, der in der vergangenen Woche Spam blockiert hat, eine Zusammenfassungs-E-Mail mit der Gesamtzahl, den meistbetroffenen Formularen und den häufigsten Gründen. Schalte sie unter Weekly spam summary in den Workspace-Einstellungen aus oder über den Link in der E-Mail.
Honeypot
Füge ein verstecktes Input hinzu, das Menschen nie ausfüllen. Der Standardname ist _gotcha; du kannst ihn pro Formular unter Honeypot field in den Einstellungen des Formulars ändern. Techniken zum Verstecken findest du unter HTML-Formulare.
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />Spam-Bewertung
Jeder Post bekommt anhand dieser Signale eine Bewertung. Ab 5 wird er als Spam gespeichert.
| Signal | Grund-Code | Bewertung |
|---|---|---|
| Der Honeypot ist ausgefüllt | honeypot | +5 |
| Weniger als 2 Sekunden nach dem Rendern des Formulars gesendet | timestamp_fast | +3 |
| Der signierte Render-Zeitstempel ist gefälscht oder älter als 24 Stunden | timestamp_invalid | +3 |
| Ein Link in einem Namens- oder Betreff-Feld | url_in_name | +3 |
| Dieselben Felder wurden in den letzten 24 Stunden an dieses Formular gesendet | duplicate | +3 |
| Insgesamt drei oder mehr Links | many_urls | +2 |
| Eine bekannte Spam-Phrase (22 eingebaut) | keyword | +2 |
| Eine E-Mail-Adresse auf einer Wegwerf-E-Mail-Domain | disposable_email | +2 |
- Den Render-Zeitstempel gibt es nur, wenn das Formular vom SDK oder von der shadcn/ui-Komponente gerendert wird, die ein signiertes
_ikiform_tssenden. Einfache HTML-Posts ohne ihn werden nicht bestraft. - Ein Namensfeld ist jedes Feld, dessen Name
name,firstname,lastname,fullname,surnameodersubjectenthält, aber keine Wörter wiecompany,websiteoderdomain. - Zwei Gründe erzwingen Spam unabhängig von der Bewertung:
origin_mismatchaus den erlaubten Domains undcaptcha_unavailable, wenn Turnstile nicht erreichbar ist.
Menschlichkeitsprüfung
Jedes Formular hat eine Einstellung Spam check mit drei Optionen. Sie ist standardmäßig aus, damit bestehende fetch- und curl-Integrationen weiter funktionieren, wenn du ein Formular erstellst.
| Option | Was er macht |
|---|---|
| Aus | Keine Challenge. Honeypot, Zeitstempel und Bewertung laufen weiterhin. |
| Ikiform (empfohlen) | Cloudflare Turnstile, von Ikiform auf ikiform.com ausgeführt. Kein Cloudflare-Konto und keine Schlüssel nötig. |
| Eigene Turnstile-Schlüssel | Dein Turnstile-Widget und dein geheimer Schlüssel. Der Hostname des Tokens wird mit deinen erlaubten Domains abgeglichen. |
So läuft die Ikiform-Prüfung
HTML-Formular
- Der Browser sendet das Formular
- Noch kein Token: ikiform.com zeigt eine kurze Prüfseite
- Turnstile läuft, die Seite sendet dieselben Felder mit einem Token erneut
- 303 zu deiner Weiterleitung oder zur Danke-Seite
JavaScript
- challenge(formId) bindet einen versteckten ikiform.com-Frame ein
- Turnstile läuft und zeigt sich nur, wenn ein Klick nötig ist
- submit(formId, data, { turnstileToken })
- 201 mit der Einsendungs-ID
Server mit Secret Key
- POST mit Authorization: Bearer ik_sk_...
- Die Ikiform-Prüfung wird übersprungen
- 201 mit der Einsendungs-ID
import { challenge, submit } from "@ikiform/sdk";
const form = document.querySelector("form");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const turnstileToken = await challenge("frm_xxxxxxxxxxxxxxxx");
const result = await submit("frm_xxxxxxxxxxxxxxxx", new FormData(form), { turnstileToken });
if (result.ok) form.replaceWith("Thanks, we got it.");
});Tokens sind nur einmal verwendbar und gelten 300 Sekunden, hol dir also eins pro Absenden. Ein JSON-Post ohne Token bekommt 403 challenge_required mit einer challenge_url; ein Token, das die Verifizierung nicht besteht, bekommt 403 captcha_failed.
{
"ok": false,
"error": {
"code": "challenge_required",
"message": "Complete the human check, then send the form again.",
"challenge_url": "https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx/challenge"
},
"request_id": "req_01k7v2c9t3e8m5q4x6z0a1b2c3"
}captcha_unavailable gespeichert, sodass du ihn wiederherstellen kannst, statt ihn zu verlieren.Eigene Turnstile-Schlüssel
Füge deinen Site Key und deinen geheimen Schlüssel in die Einstellungen des Formulars ein. Das Secret wird verschlüsselt gespeichert. Rendere das Widget in deinem Formular, damit es cf-turnstile-response zum Post hinzufügt, oder übergib das Token an submit als turnstileToken. Posts ohne gültiges Token bekommen 403 captcha_failed, auch Posts mit einem geheimen API-Schlüssel.
Erlaubte Domains
Liste die Domains, auf denen dein Formular läuft, unter Allowed domains auf. Ein Post muss dann von einer davon oder einer Subdomain kommen, beurteilt anhand des Origin-Headers oder des Referer, wenn es keinen Origin gibt. Lass die Liste leer, um Posts von jeder Site zu akzeptieren.
| Erlaubte Domains | Post von | Passt |
|---|---|---|
example.com | https://example.com | Ja |
example.com | https://www.example.com | Ja, Subdomain |
example.com | http://localhost:3000 | Nein, füge localhost während der Entwicklung hinzu |
example.com | https://example.co | Nein |
app.example.com | https://example.com | Nein, eine übergeordnete Domain passt nicht |
When a post comes from another site legt fest, was bei einer Abweichung passiert: Mark as spam (Standard) oder Reject mit 403 origin_not_allowed. Posts mit einem geheimen API-Schlüssel überspringen diese Prüfung. Die erlaubten Domains legen außerdem fest, welchen _redirect-Zielen gefolgt wird und wo der Prüf-Frame von Ikiform eingebettet werden darf.
Rate-Limits
Jedes Formular hat ein Rate limit-Preset, exakt gezählt pro Besucher-IP und Formular. Standard erlaubt 5 Posts pro Minute, Relaxed 20 pro Minute und Strict 2 alle 10 Minuten. Die vollständigen Regeln stehen unter Rate-Limits.