splitforms.com
HTML · CONTACT FORM

Contact form for any HTML website

The simplest possible setup. Drop one `

` tag into your HTML and submissions land in your inbox. No JavaScript, no backend, no server to maintain. Works on GitHub Pages, S3, Cloudflare Pages, plain Apache — anywhere static HTML can be served.

1,000 free submissions every month.·No credit card.
contact.htmlhtml13 lines
01<form action="https://splitforms.com/api/submit" method="POST">
02 <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
03 <input type="hidden" name="redirect" value="https://yoursite.com/thanks" />
04
05 <input type="text" name="name" placeholder="Your name" required />
06 <input type="email" name="email" placeholder="you@example.com" required />
07 <textarea name="message" placeholder="What's up?" required></textarea>
08
09 <!-- Honeypot for spam — hidden from humans -->
10 <input type="checkbox" name="botcheck" style="display:none" tabindex="-1" />
11
12 <button type="submit">Send message</button>
13</form>
1,000
submissions / mo, free
14ms
median latency, edge
0
lines of backend code
17+
frameworks supported
✶ Live preview

What your HTML contact form actually looks like.

Drop-in form backend with spam filtering, signed webhooks, and a real submissions dashboard. The same code in this preview is what you copy into your HTML project — no SDK, no plugin, no PHP.

  • 1,000 submissions per month, free forever
  • Honeypot + AI spam classifier on every plan
  • Signed webhooks to Slack, Discord, your server
HTML contact form on Splitforms — drop-in form backend with spam filtering and webhooks
§ 01Setup3 steps · 60 seconds · zero config

Ship a HTML contact form without a backend.

No SDK, no PHP, no plugin. Your form posts standard FormData to one URL — submissions land in your inbox.

STEP 01GENERATE

Get your free access key

Verify your email and your access key is generated instantly. Free for 1,000 submissions per month, forever.

Create your form

By signing up, you agree to our terms and privacy policy.

STEP 02EMBED

Drop in the HTML code

Copy the HTML snippet on the right and paste it into your project. Replace YOUR_ACCESS_KEY with the key from step 1.

snippethtml
<form action="https://splitforms.com/api/submit" method="POST">
…
STEP 03RECEIVE

Submissions land in your inbox

Hits your dashboard and email in seconds. Forward to Slack, Discord, Sheets, Notion, or any signed webhook URL.

inbox · 1 newjust now
FROM contact@yoursite.com
New HTML form submission
Maya Iyer maya@studio71.co
Loved the new pricing page — quick question about the 4-year plan. Are usage limits per project or account-wide?
§ 02Live demosandboxed · no key required · no submission sent

Try it now — no signup, no key.

This is a styled HTML preview of what your HTML form will look like. Submitting opens a confirmation, no real request is sent.

preview · htmllocalhost:3000
✦ what just happened

Your HTML form posts FormData to /api/submit. Splitforms validates the access key, runs the spam classifier, and forwards the parsed submission to your inbox plus the dashboard.

  • 14ms median round-trip from the edge.
  • Honeypot + classifier, no CAPTCHA.
  • Per-domain key locking out of the box.
REQUEST · POST /api/submit
{
  "access_key": "sk_live_4f9a_••••",
  "name":       "Maya Iyer",
  "email":      "maya@studio71.co",
  "message":    "…"
}
← 200 OK · { "success": true } · 14ms
§ 03Best practices5 rules · production-tested

How to ship this without regrets.

Five rules that make the difference between a form that works in the demo and a form that survives launch traffic.

  1. 01

    Always set `method="POST"` explicitly. The HTML default is GET, which won't work with splitforms.

  2. 02

    Add a `redirect` hidden field pointing to a `/thanks.html` page so users without JS still get a confirmation page after submitting.

  3. 03

    Lock the access key to your domain in the splitforms dashboard. The key lives in your HTML source — anyone can copy it, but domain locking makes it inert elsewhere.

  4. 04

    Use `required` attributes on essential inputs. Browsers enforce these client-side without JavaScript — gives users immediate feedback if they forget a field.

  5. 05

    Add `autocomplete="name|email|tel|…"` attributes to inputs. Browsers fill them automatically, dramatically improving conversion on mobile.

§ 04Common gotchas in HTML6 edge cases worth knowing

What bites people who skip the docs.

Worth a 60-second skim before you ship to production. Each one has caused a HTML support ticket at least once.

⚠ gotcha

method="GET" turns your form into a URL query string

If you forget method="POST" (or omit it — GET is the HTML default), the browser appends form fields to the URL: ?name=Maya&email=…. Splitforms's endpoint returns 405 Method Not Allowed because it only accepts POST. Always specify the method explicitly.

⚠ gotcha

Multiple inputs with the same `name` only send the last value

If you accidentally name two fields email, FormData posts both — but the splitforms dashboard shows the last one. For checkbox groups, use name="interests[]" or unique names per checkbox.

⚠ gotcha

File inputs require enctype="multipart/form-data"

Standard forms submit as application/x-www-form-urlencoded, which can't carry binary file data. If you add <input type="file">, also add enctype="multipart/form-data" to the form tag — otherwise the file silently doesn't upload.

⚠ gotcha

Hidden honeypot field needs to be invisible to bots' DOM parsers

style="display:none" is what splitforms uses, but some sophisticated bots ignore display:none. Stack defenses: display:none + tabindex="-1" + aria-hidden="true" + an off-screen label. Splitforms's classifier catches the rest.

⚠ gotcha

GitHub Pages can't post to https without HTTPS on your domain

Mixed-content errors: if your GitHub Pages site is served over HTTP (rare but possible on custom domains without HTTPS toggled), the browser blocks the POST to https://splitforms.com. Enforce HTTPS in your custom domain settings.

⚠ gotcha

<button> outside the <form> tag does nothing on submit

Browsers only treat a button as a submit trigger when it's a descendant of the form element. If your CSS layout requires the submit button to live outside the <form> (e.g. a sticky bar at the page bottom), the form will never submit on click — Enter inside an input still works. Fix it by adding form="contact-form" on the button, matching an id="contact-form" on the form. The HTML5 form-attribute association is widely supported but easy to forget.

§ 04bNative HTML forms…and where they break down

How HTML handles forms without splitforms.

The shape of the problem before splitforms enters the picture — and the gap it fills for HTML specifically.

Plain HTML has no built-in way to deliver a form submission anywhere — the spec only covers serializing fields and either GETting or POSTing them to whatever URL you put in action. Without a backend, the historical fallback is mailto: links (broken on Gmail, Outlook web, and most mobile devices) or PHP on shared hosts (extinct on S3, GitHub Pages, Cloudflare Pages, Netlify-static). That's the gap splitforms fills: you keep using the same <form action method=POST> HTML you already wrote, and the action points at our endpoint instead of a server you'd otherwise have to operate.

§ 04cAlternative integration patterns2 ways to wire it

Two ways to ship splitforms on HTML.

Pick the pattern that matches your constraints — JS budget, key-exposure tolerance, server-side opacity. Both produce the same result.

PATTERN A

Pattern A — pure HTML with redirect-on-success

The simplest possible setup: zero JavaScript, full graceful degradation, the browser handles the round-trip. Splitforms 302s to your redirect URL on success, so users always land on a thank-you page even with JavaScript disabled or a flaky network.

pattern-a.htmlhtml9 lines
01<form action="https://splitforms.com/api/submit" method="POST">
02 <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
03 <input type="hidden" name="redirect" value="https://yoursite.com/thanks.html" />
04 <input name="name" required />
05 <input name="email" type="email" required />
06 <textarea name="message" required></textarea>
07 <input type="checkbox" name="botcheck" style="display:none" tabindex="-1" />
08 <button type="submit">Send</button>
09</form>
PATTERN B

Pattern B — HTML with progressive-enhancement fetch

Same HTML, plus a tiny inline <script> that intercepts the submit, posts via fetch, and renders inline status — without a framework. Falls back to native form behaviour if JS fails to load.

pattern-b.htmlhtml14 lines
01<form id="cf" action="https://splitforms.com/api/submit" method="POST">
02 <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
03 <input name="email" type="email" required />
04 <textarea name="message" required></textarea>
05 <button type="submit">Send</button>
06 <p id="msg" aria-live="polite"></p>
07</form>
08<script>
09 document.getElementById("cf").addEventListener("submit", async (e) => {
10 e.preventDefault();
11 const r = await fetch(e.target.action, { method: "POST", body: new FormData(e.target) });
12 document.getElementById("msg").textContent = (await r.json()).success ? "Thanks!" : "Try again";
13 });
14</script>
§ 04dDeployment notes for HTMLhosting · env vars · CSP

Shipping HTML + splitforms to production.

Host-specific gotchas, env-var conventions, and the boring-but-load-bearing details for putting this on the public internet.

Plain HTML deploys to anywhere that serves files: GitHub Pages, S3 + CloudFront, Cloudflare Pages, Netlify, Vercel, plain Apache/nginx, even Dropbox public folders (RIP). The form posts cross-origin from the browser to splitforms.com, so the host is irrelevant to delivery — but enforce HTTPS on your domain, otherwise the browser blocks the mixed-content POST. On GitHub Pages, toggle 'Enforce HTTPS' under Settings → Pages. On S3, terminate TLS at CloudFront. Lock the splitforms access key to your custom domain in the dashboard so a leaked key from View Source is inert elsewhere.

§ 05Comparisonvs native html

splitforms vs native html.

What you get for free vs what you build, pay for, or do without.

FeatureNative HTMLsplitforms
Setup timeStand up backend + email + spam filterPaste one form tag
JavaScript requiredOptional0 KB
Spam filterDIY honeypot or reCAPTCHAHoneypot + classifier built-in
Submission storageDatabase + authDashboard included free
Email deliverabilityConfigure SPF/DKIM/DMARCPre-configured sender
CostServer + email (~$5+/mo)Free (1,000/mo)
§ 07Questions6 answered

Things developers ask before they integrate.

Direct answers, no marketing fluff. Missing one? Email hello@splitforms.com.

01How do I add a contact form to a plain HTML website?
Paste the snippet above into your HTML file. Replace YOUR_ACCESS_KEY with the key from your splitforms dashboard. Submissions go to your inbox immediately. No JavaScript, no build step, no install.
02Does splitforms work with GitHub Pages, S3, Cloudflare Pages, and other static hosts?
Yes — every static host. The form posts to splitforms.com from the browser, so the host only serves the HTML. Lock the access key to your custom domain (or *.github.io / *.pages.dev) in the splitforms dashboard.
03How do I handle form errors with pure HTML (no JavaScript)?
Splitforms returns a default error page on failures (invalid key, spam, rate-limit). You can customize that page in the splitforms dashboard → Settings → Error Page. For inline error handling, you'd need a small JS snippet — see the AJAX page.
04Can I use splitforms with HTML forms that have file uploads?
File uploads are on the splitforms roadmap (Q3 2026). Today, file inputs in your form will be silently dropped from the submission — the rest of the fields go through fine.
05How do I customize the success / redirect behavior?
Add a hidden redirect input: <input type="hidden" name="redirect" value="https://yoursite.com/thanks.html">. After a successful submit, splitforms 302s the browser there. The /thanks.html page is yours — build it however you like.
06Is the form really spam-protected without a CAPTCHA?
Yes. The hidden honeypot field catches naive bots; a tuned classifier scores everything else and quarantines anything that looks automated. CAPTCHA hurts conversion (5-15% drop, depending on study) so we don't use one. If you ever need stricter protection, the Pro plan adds custom rules.
✻ ✻ ✻

Ship your HTML contact form in 60 seconds.

1,000 free submissions per month. No credit card. Lock the access key to your domains, paste the snippet, watch submissions land in your inbox.

Get free access key →Read the docs
v0.1 · founders pricing locked in · early access open