HTML forms
Point a plain HTML form at your endpoint. Field names, the spam trap, redirects back to your site and the limits that apply, with no JavaScript at all.
The form
A plain HTML form needs two attributes to work with MakeTheForm: action set to your endpoint and method set to POST. No JavaScript, no build step. This works on any static host and in any tool that lets you edit a form's markup.
<form action="https://mtform.co/f/your-form-key" method="POST">
<label>
Name
<input name="name" autocomplete="name" required>
</label>
<label>
Email
<input type="email" name="email" autocomplete="email" required>
</label>
<label>
Message
<textarea name="message" required></textarea>
</label>
<!-- Spam trap: hidden from people, tempting to bots. Leave it empty. -->
<input
type="text"
name="_mtf_honeypot"
tabindex="-1"
autocomplete="off"
aria-hidden="true"
style="position:absolute;left:-9999px"
>
<button type="submit">Send</button>
</form>Keep your own classes, layout and validation attributes. The endpoint only reads what the browser sends: field names and values.
Field names
Every input you want to receive needs a name. An input without one is never sent by the browser, so it cannot reach us. The name becomes the field label in your dashboard and your notification email, in the order the fields were submitted.
- Repeated names are kept as separate values, not merged or overwritten. A group of checkboxes that share a name arrives as one value per ticked box.
- Name the address field
email. New forms use that field as the Reply-To of the notification email, so replying goes straight to the submitter. You can pick a different field in the form's notification settings. - Names starting with
_mtf_are reserved for control fields. They are removed before the submission is stored, so do not use that prefix for your own data.
<fieldset>
<legend>Interested in</legend>
<label><input type="checkbox" name="interest" value="design"> Design</label>
<label><input type="checkbox" name="interest" value="development"> Development</label>
</fieldset>Control fields
A few hidden inputs change how a submission is handled. They are read, acted on, and never shown to you as data.
| Field | What it does |
|---|---|
| _mtf_honeypot | The spam trap. It must stay empty. A filled one is treated as a bot: the sender sees success and nothing is stored. |
| _mtf_redirect | Where to send the browser after a successful submission. Only honoured for a URL on one of the form’s allowed domains. |
| _mtf_subject | The notification email’s subject for this submission, overriding the form’s subject setting. {{field}} inserts a submitted value, as in the setting. |
| _mtf_reply_to | The name of the field whose value becomes the notification’s Reply-To, overriding the form’s Reply-To setting. Ignored unless that field is in the submission and holds one email address. |
| _mtf_turnstile_token | The Cloudflare Turnstile token, when the form uses a bot challenge. Cloudflare’s default name, cf-turnstile-response, works too. |
position:absolute;left:-9999px as the snippet does, with tabindex="-1" and autocomplete="off". Bots skip fields that are display:none or type="hidden", and a required honeypot blocks real people. If your markup already uses _gotcha, _honeypot or _honey, those names are treated as the honeypot as well.After the visitor submits
On success the browser gets a 303 redirect. Without a redirect field it lands on a plain confirmation page on the endpoint host. To bring visitors back to your own site, add the redirect field:
<input type="hidden" name="_mtf_redirect" value="https://example.com/thanks">The target must be an absolute URL on one of the form's allowed domains. Anything else, including a relative path, is ignored and the confirmation page is shown instead. This stops the endpoint being used as an open redirect.
Because it is a 303, refreshing the thank-you page does not resend the form. A double-clicked button is also safe: the same submission from the same visitor within a minute is only stored once.
If something goes wrong, for example the form is paused or the visitor is rate limited, the browser shows a short error page with the matching HTTP status. The visitor has to go back to try again. If you want errors shown next to the form instead, submit it with fetch.
Files and limits
To accept attachments, add enctype="multipart/form-data" to the form and an <input type="file">. Without the enctype the browser sends only the filename. File uploads are covered in File uploads.
| Limit | Value |
|---|---|
| Request body, excluding files | 256 KB |
| Fields per submission | 100 |
| Field name | 128 bytes |
| Single field value | 20 KB |
An oversized submission is refused with 413, never truncated. The full table is in the API reference.