Netlify Forms
Last updated October 19, 2026. SpamFlip is operated by MLN Learning LLC.
Netlify's forms setup says to enable form detection, then deploy HTML that includes a form with a unique name and either data-netlify="true" or netlify. Their build parses that HTML, removes the attribute, and injects <input type="hidden" name="form-name"> whose value is the form name. A form rendered only in the browser is not in that scan unless a matching static form is also in the deploy.
The same page says an AJAX submission of a text form must POST URL-encoded data to a path on that site, with Content-Type: application/x-www-form-urlencoded. Their example is fetch("/"). They say JSON is not supported. For a file upload they say to send FormData without setting Content-Type, still to a path on that site.
Markup
data-spamflip is what the snippet looks for. data-netlify is what Netlify's build looks for. Set method="POST". The hidden form-name field below is the field Netlify says it injects. Putting it in the source means it is still present if a later render is not the HTML their build scanned. The HTML forms page describes the snippet itself.
<script src="https://spamflip.app/sf.js" data-site-key="YOUR_SITE_KEY" defer></script> <form name="contact" method="POST" action="/" data-netlify="true" data-spamflip> <input type="hidden" name="form-name" value="contact" /> <input name="email" type="email" /> <textarea name="message"></textarea> <button type="submit">Send</button> </form>
The request SpamFlip sends
When the proxy responds, the snippet does not POST to the form action. On a clean verdict with no file upload, SpamFlip's server POSTs the string fields to the https URL saved on the site. The method is POST. The content type is application/x-www-form-urlencoded. Field names are the names from the form, including form-name when that input is present. The request sets Accept to application/json. File inputs are not included. Fields named sf_hp, sf_site, sf_field_to_submit_ms, sf_fill_velocity_ms, sf_mouse_moved, sf_token, and the rotating honeypot name are removed.
Netlify's forms setup says an AJAX text form uses that same content type, posted to a path on the site. The content type of this text forward matches that sentence. The saved URL is the https address stored on the site. This page does not claim that the server POST satisfies Netlify's AJAX requirements, and it does not claim that Netlify stores a submission SpamFlip forwards. A check with a Netlify account has not been run.
A submission that includes a file is still sent as multipart form data, and the file bytes are not included. Netlify's forms setup says a file upload is FormData without a Content-Type header. The multipart request above is only the string fields.
If the handler responds with 301, 302, or 303, SpamFlip treats the delivery as successful and does not POST the fields again. It also does not request the redirect location. The visitor receives HTTP 200 and {"status":"ok"}. A 307 or 308 repeats the same POST at the location. Any other redirect status is requested with GET and no body. At most two redirects are followed. A followed target that is not public https fails the delivery.
The browser submits the form to its action only when both requests to SpamFlip fail in the browser. Each waits up to 12 seconds. That fallback uses the form's own method and action, after the honeypot fields are removed. A response that arrives and is not successful does not fall through to the action. A quarantine or spam verdict is not forwarded.