splitforms.com
guide · form types

Registration Form in HTML — Working Code for 2026

A registration form with name, email, password, and confirm-password fields — semantic HTML, native validation, accessibility-first labels. POSTs to splitforms (free 500/mo). The form code, the validation rules, and the backend integration on one page.

html
<form action="https://splitforms.com/api/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
  <input type="hidden" name="_subject"   value="New registration" />
  <input type="hidden" name="redirect"   value="https://yoursite.com/welcome" />

  <label>
    Full name
    <input name="name" type="text" required minlength="2" autocomplete="name" />
  </label>

  <label>
    Email
    <input name="email" type="email" required autocomplete="email" />
  </label>

  <label>
    Password
    <input name="password" type="password" required minlength="8"
           autocomplete="new-password" />
  </label>

  <label>
    Confirm password
    <input name="password_confirm" type="password" required minlength="8"
           autocomplete="new-password" />
  </label>

  <label>
    <input type="checkbox" name="agree_terms" required />
    I agree to the <a href="/terms">terms of service</a>
  </label>

  <input type="checkbox" name="botcheck" style="display:none" tabindex="-1" />
  <button type="submit">Create account</button>
</form>

A registration form is a contact form with stricter validation rules. Same `<form>` wrapper, same submit mechanics, but every field has more requirements: passwords must be a minimum length, emails must be unique, terms must be accepted. Most of the validation work happens server-side (on your backend) — the HTML's job is to fail loudly on obvious mistakes before the user even submits.

The form above uses every native validation primitive: `required` for mandatory fields, `type="email"` for email format checking, `minlength="8"` for password length, the terms checkbox uses `required` so the user can't submit without agreeing. Modern browsers show inline error messages automatically — no JavaScript needed for the baseline.

Password confirmation is the one case where native HTML falls short. There's no `equalTo` attribute, so you need ~5 lines of JavaScript to compare the two password fields and show an error if they don't match. The snippet for that is in the alternative-code section below.

The form POSTs to splitforms's `/api/submit` endpoint. splitforms stores the registration and can email you on every plan, while Starter can also fire webhooks. If you're building a real registration system (where users actually log in), you'll want a database-backed signup flow — use splitforms for the lead-capture form, then write users to your auth provider via a webhook handler.

Password-match validation (5 lines of vanilla JS)

javascript
const form = document.querySelector("form");
const password = form.querySelector("[name=password]");
const confirm = form.querySelector("[name=password_confirm]");

confirm.addEventListener("input", () => {
  confirm.setCustomValidity(
    confirm.value === password.value ? "" : "Passwords don't match"
  );
});

How to set this up

Step 01

Use semantic input types

type=email for email, type=password for passwords, autocomplete=name/email/new-password for browser autofill support.

Step 02

Add native validation

required, minlength, type=email — the browser blocks malformed submissions before they hit the network.

Step 03

Handle password confirmation in JS

Native HTML has no equalTo. 5 lines of JS using setCustomValidity does the job — no library needed.

Step 04

POST to splitforms

Submissions land in your dashboard and can email your inbox. Starter can also webhook into your auth provider if you're building a full account system.

Native validation, password-match in 5 lines of JS, splitforms backend.

Frequently asked questions

How do I make a registration form in HTML?

Use a <form action method=POST> with inputs for name, email, password, password confirmation, and a terms-of-service checkbox. Use type="email" and type="password" for native validation, required for mandatory fields, minlength="8" for password length. POST to a backend service like splitforms (free 500/mo) or your own /api/register endpoint.

Should I use type="password" or a custom show/hide toggle?

type="password" is the baseline — required for password manager compatibility, accessibility, and browser autofill. Add a show/hide button via JS if you want, but keep the input as type="password" by default.

How do I validate that the two passwords match?

Use setCustomValidity in JS. On every input event on the confirm field, set it to '' if values match, or 'Passwords don\'t match' if they don't. The native validation UI then displays the error like any other required-field error.

Is splitforms the right backend for a real registration system?

splitforms is the right backend for capturing the registration (email goes to you, submission stored, webhook fires). For full account creation (writing the user to your auth database, sending a confirmation email link, etc.), wire a webhook from splitforms to your auth provider — Supabase, Clerk, Auth0, etc.

Do I need a CAPTCHA?

Probably not. The honeypot field + splitforms's AI spam classifier catches most bot submissions. Add CAPTCHA only if you're seeing real human-driven abuse — which is rare for a registration form.

Related guides

Ship the form, not the backend.

Free for 500 submissions/month. Owner email delivery, AI spam filtering, and a real dashboard are included on Free. Starter adds signed webhooks. No credit card.

Get a free access key →