Languages and runtimes
An HTML contact form that just works
An HTML form has been able to POST since 1995. The only thing missing has always been something on the other end to receive it, which is why so many static sites end up with a mailto: link. Set the action attribute to a WebForms endpoint and the form works: submissions are stored, filtered for spam and forwarded to email, Slack or a webhook. No JavaScript is involved at any point.
Setup
Create a form and copy the endpoint
Sign up, create a form, copy the URL. That URL is the value of your action attribute.
Paste the markup
Every input needs a name attribute - that name becomes the field label on the submission.
Point _next at your thank-you page
After a successful submit the browser is redirected there. Leave it out and the visitor goes back to the page they came from.
HTML examples
Swap in your own endpoint and these run as-is.
The complete integration. Nothing else is required.
<form action="https://send.webforms.to/wft_your_key" method="POST">
<label>
Name
<input type="text" name="name" required />
</label>
<label>
Email
<input type="email" name="email" required />
</label>
<label>
Message
<textarea name="message" rows="5" required></textarea>
</label>
<!-- Redirect here after a successful submit -->
<input type="hidden" name="_next" value="https://example.com/thanks" />
<!-- Sets the subject line of the notification email -->
<input type="hidden" name="_subject" value="New enquiry from the website" />
<!-- Honeypot: people never see it, bots fill it, we drop those -->
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off"
style="position:absolute;left:-9999px" aria-hidden="true" />
<button type="submit">Send message</button>
</form>Checkboxes, radios, selects and file inputs all behave as you would expect. Repeated names collapse into an array.
<form action="https://send.webforms.to/wft_your_key" method="POST">
<input type="text" name="company" />
<fieldset>
<legend>What do you need?</legend>
<label><input type="checkbox" name="interests" value="design" /> Design</label>
<label><input type="checkbox" name="interests" value="build" /> Build</label>
<label><input type="checkbox" name="interests" value="hosting" /> Hosting</label>
</fieldset>
<select name="budget">
<option value="">Choose…</option>
<option value="under-5k">Under $5k</option>
<option value="5k-20k">$5k – $20k</option>
<option value="20k-plus">$20k+</option>
</select>
<!-- Hitting reply in your inbox answers the sender, not us -->
<input type="hidden" name="_replyto" value="" />
<button type="submit">Send</button>
</form>Worth knowing
- Field names beginning with an underscore are directives, not data: _next, _redirect, _subject, _replyto, _cc, _from_name and _gotcha.
- Set _replyto to the visitor's email field value and replying in your inbox goes straight to them.
HTML form FAQ
Yes. PHP's mail() was only ever the receiving end. Point the action attribute at a hosted endpoint and the same form works on a static host with no server-side language at all.
Yes. Nothing runs on your host - the browser posts directly to the endpoint, so GitHub Pages, S3, Netlify, Cloudflare Pages and plain nginx all work identically.
Include the hidden _gotcha honeypot shown above. Bots fill it and those submissions are dropped silently. A time trap and disposable-email blocking run automatically, and you can enable Turnstile, hCaptcha or reCAPTCHA if you want a challenge as well.
To the URL in _next, if you set one. Otherwise back to the page the form was on.
Related guides
Ready to wire up your HTML form?
Free for 300 submissions a month. Endpoint in under a minute, no card required.
Start free