On this page
Your options, compared
Four ways to receive a contact form. They differ in how much of the backend you end up owning.
| Approach | Server code | Spam protection | Delivery | Upkeep |
|---|---|---|---|---|
| Your own API route and email SDK | You write it | You build it | Your email provider | Keys, limits, patches |
| A serverless function | One function | You build it | Your email provider | Function and key |
| Your host’s form feature | None | The host’s own filter | The host’s dashboard | Tied to one host |
| Form endpoint | None | Built in | Email, inbox and integrations | None |
The minimal integration
A fetch-based submit handler for when you want an inline success message instead of a full-page redirect. Plain HTML (no JS) works too: just set the form action to your endpoint.
const form = document.querySelector('#contact-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const button = form.querySelector('button[type="submit"]');
button.disabled = true;
try {
const response = await fetch('https://mtform.co/f/your-form-key', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(Object.fromEntries(new FormData(form))),
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.error?.message ?? 'Unable to send your message.');
}
form.reset();
// Replace with your own success UI.
console.log('Sent', result.submission_id);
} catch (error) {
// Values are preserved because we never reset on failure.
console.error(error.message);
} finally {
button.disabled = false;
}
});Swap in your own endpoint. On failure the handler shows the returned error.message and keeps what the visitor typed.
Step by step
- 1
Pick your front end
Keep whatever you already have: plain HTML, React, Vue, Astro, or an AI-generated page. The endpoint doesn’t care what rendered the form.
- 2
Create an endpoint
Create a form in MakeTheForm to get a public endpoint URL and an inbox. Nothing to deploy or host.
- 3
Wire it up
Either set the form’s action to the endpoint (no JS) or POST to it with fetch for an inline success message. Add the hidden honeypot field for free spam protection.
- 4
Verify and go live
Verify your recipient once and submit a test. It lands in your inbox and by email. With delivery you can actually see.
Why an email API key in the browser doesn’t work
Calling an email provider straight from the page looks like a backend-free shortcut. It puts your secret key in JavaScript that every visitor downloads, so anyone can copy it and send mail as you.
// Anyone who opens devtools now has your key.
await fetch("https://api.email-provider.example/send", {
method: "POST",
headers: { Authorization: "Bearer sk_live_…" },
body: JSON.stringify({ to: "you@example.com", text: message }),
});Common pitfalls
Reaching for a serverless function too early
A one-off Lambda or edge function to catch a form is a deploy target, a cold start, and a spam problem you now own. For a contact form, an endpoint is less to build and less to keep alive.
Forgetting spam protection
A raw POST target gets found by bots within days. Use the honeypot field and, if needed, turn on Turnstile: both belong on every plan, not just paid ones.
Troubleshooting
| Symptom | What’s happening | Fix |
|---|---|---|
| CORS error | Your fetch sent a non-simple request or a disallowed header. | POST JSON with Content-Type: application/json; the endpoint handles the CORS preflight for browser origins. |
| 429 | You hit the burst rate limit while testing repeatedly. | Wait for the window in Retry-After. Rate-limited requests never count against your submission quota. |
Frequently asked questions
Can you make a contact form without a backend?
Yes. Point the form at a hosted form endpoint that receives, filters, stores, and emails the submission. You write only front-end code; the endpoint is the backend, managed for you.
What’s the difference between a form endpoint and building my own backend?
A form endpoint gives you receipt, spam filtering, storage, email delivery, and retry visibility out of the box. Building your own means writing and hosting a server, wiring a mail provider, and handling spam and deliverability yourself.
Is a form endpoint the same as a serverless contact form?
It does the same job without the function. A serverless contact form is code you write and deploy to a function platform, plus an email provider and your own spam handling. A form endpoint is that function already built and run for you, so there is nothing to deploy.
Is a form endpoint secure to use in client-side code?
Yes. The public form key is a non-secret address meant for the browser. Your destination email is never exposed in page source, and abuse is handled by rate limits, origin rules, and spam filtering.
Keep going
Last reviewed by the MakeTheForm team.