splitforms.com

HTML · FORM CONTROL

HTML Checkbox — toggle and multi-select (live demo)

Last reviewed

A checkbox is an <input type="checkbox"> for an on/off choice. When checked it submits name=value, or name=on if it has no value attribute; when unchecked it submits nothing at all, not even its name. Give several boxes the same name to collect multiple answers. Below is a working form with checkboxes.

  • 500 free total
  • No backend
  • Copy-paste ready
Live demo · nothing is sent

What gets submitted

Fill in the form above and press its button. The demo stops the request and lists every name=value pair the browser would send, plus the controls it leaves out.

With a free access key in the form, these fields land in your splitforms dashboard; access_key and botcheck are read by splitforms, not stored as lead data.

Copy-paste code

HTML Checkbox code you can paste today.

Replace YOUR_ACCESS_KEY with a key from your free splitforms dashboard. The form posts to one endpoint — submissions land in your inbox and dashboard with spam filtering built in.

Get free access key
checkbox.html
<form action="https://splitforms.com/api/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">

  <label for="name">Name</label>
  <input type="text" id="name" name="name" required>

  <fieldset>
    <legend>I'm interested in (tick all that apply)</legend>
    <label><input type="checkbox" name="interest" value="newsletter"> Newsletter</label>
    <label><input type="checkbox" name="interest" value="beta"> Beta access</label>
    <label><input type="checkbox" name="interest" value="demo"> Product demo</label>
  </fieldset>

  <label><input type="checkbox" name="agree_terms" value="yes" required> I agree to the terms</label>

  <button type="submit">Send</button>
</form>

What gets submitted

What does a checkbox send when the form is submitted?

A checked checkbox sends its name and value; an unchecked one sends nothing, so the key is missing rather than false. Boxes that share a name each add their own pair, and a disabled box is skipped even when it is checked.

What does a checkbox send when the form is submitted?
Checkbox stateWhat the browser sendsNotes
Checked, with value="yes"agree=yesThe value is sent exactly as written.
Checked, no value attributeagree=onon is the default value, so always set a meaningful one.
UncheckedNothing: the agree key is absentNo agree= and no false. Treat a missing key as unchecked.
Several checked boxes with the same nameinterest=beta&interest=demoOne pair per checked box, in page order. Object.fromEntries(new FormData(form)) keeps only the last; read them all with formData.getAll("interest").
disabled (checked or not)NothingDisabled controls are skipped. To send a fixed value, use a hidden input instead.
indeterminate set in JavaScriptWhatever its checked state saysIndeterminate only changes how the box looks. It is not an HTML attribute and is never submitted.
No name attributeNothingOnly named controls are submitted; id does not count.

These are the checkbox rows only. The other input types are listed with their submitted values in the input types table.

Sources: WHATWG HTML Standard: constructing the entry list · WHATWG HTML Standard: checkbox state · WHATWG HTML Standard: indeterminate · MDN: checkbox value · MDN: FormData.getAll()

Attributes · <input type="checkbox">

Which HTML Checkbox attributes matter?

These attributes decide how the <input type="checkbox"> behaves and what actually gets emailed to your inbox when someone submits.

HTML Checkbox attributes and what each one does
AttributeWhat it doesDocs
nameThe key the value is submitted under. Boxes in a group can share a name; each checked one adds its own name=value pair.MDN
valueWhat's sent when the box is checked. Without it, the browser submits the literal "on".MDN
checkedBoolean. Pre-checks the box when the page loads.MDN
requiredBoolean. Forces this box to be checked before the form can submit (useful for "I agree" consent). It can't express "at least one of a group".MDN
disabledGreys out the box and excludes it from submission, even when it is checked.MDN
indeterminateNot an HTML attribute: a JavaScript property (box.indeterminate = true) that draws a mixed state. It changes the look only; the box still submits by its checked state.MDN

Common mistakes

HTML Checkbox not working? Here's why.

Most broken forms come down to a few small mistakes with the <input type="checkbox">. Check these before you ship, then forward every submission to Slack or a webhook.

  1. Unchecked = not submitted

    If a checkbox is unchecked, its name is absent from the submission entirely — not sent as false. Detect this server-side as "key missing".

  2. Without value, you get "on"

    A checked checkbox with no value= submits the string "on". Always set a meaningful value so you can tell states apart.

  3. Checkbox vs radio

    Checkboxes are independent (tick any number); radios in a group are mutually exclusive (pick one). Use radios when exactly one choice is allowed.

Sources: WHATWG HTML Standard: <input type="checkbox"> · MDN: <input type="checkbox">

type="hidden"

How do I send a value when the checkbox is unchecked?

Put a hidden input with the same name before the checkbox. Unchecked, only the hidden value is sent (newsletter=no). Checked, both are sent in page order (newsletter=no&newsletter=yes), so a server that keeps the last value for a repeated name reads yes. PHP's $_POST, Rails, Django's request.POST[key] and Object.fromEntries() all keep the last value.

The hidden input must come first. Servers that keep every value (Express body parsers, splitforms) receive both no and yes when the box is ticked, so read the last one. Flask's request.form.get() returns the first value; use getlist() there.

unchecked-value.html
<form action="https://splitforms.com/api/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">

  <!-- Always sent. Must come BEFORE the checkbox. -->
  <input type="hidden" name="newsletter" value="no">
  <label>
    <input type="checkbox" name="newsletter" value="yes">
    Send me the newsletter
  </label>

  <button type="submit">Send</button>
</form>

<!-- Unchecked: newsletter=no
     Checked:   newsletter=no&newsletter=yes -->

indeterminate

How do I make a select-all checkbox with an indeterminate state?

Give the select-all box no name, so it is never submitted. When it changes, copy its checked state to every box in the group. When one of those changes, count the ticked ones: all ticked checks the select-all box, none unchecks it, and anything in between sets indeterminate = true, the mixed state.

indeterminate exists only in JavaScript and only changes the look. Clicking a box clears it, and the box still submits by its checked state.

select-all.html
<label><input type="checkbox" id="all"> Select all topics</label>

<fieldset id="topics">
  <legend>Topics</legend>
  <label><input type="checkbox" name="topic" value="pricing"> Pricing</label>
  <label><input type="checkbox" name="topic" value="api"> API</label>
  <label><input type="checkbox" name="topic" value="security"> Security</label>
</fieldset>

<script>
  const all = document.getElementById("all");
  const boxes = [...document.querySelectorAll('#topics input[type="checkbox"]')];

  all.addEventListener("change", () => {
    boxes.forEach((box) => (box.checked = all.checked));
  });

  boxes.forEach((box) =>
    box.addEventListener("change", () => {
      const ticked = boxes.filter((b) => b.checked).length;
      all.checked = ticked === boxes.length;
      all.indeterminate = ticked > 0 && ticked < boxes.length;
    }),
  );
</script>

setCustomValidity

How do I require at least one checkbox in a group?

required on a checkbox means that particular box must be ticked, so it can't say "any one of these". Instead, set a custom validity message on the first box while none is checked. The browser then blocks the submit and shows your message, exactly like a required field, and clears it as soon as one box is ticked. How plain required behaves on every control is covered in the HTML required attribute reference.

This is a browser-side check. Anyone can post to your endpoint without it, so check the group on the server too.

require-one.html
<fieldset id="topics">
  <legend>Which topics? (pick at least one)</legend>
  <label><input type="checkbox" name="topic" value="pricing"> Pricing</label>
  <label><input type="checkbox" name="topic" value="api"> API</label>
  <label><input type="checkbox" name="topic" value="security"> Security</label>
</fieldset>

<script>
  const boxes = [...document.querySelectorAll('#topics input[type="checkbox"]')];

  function checkGroup() {
    const ok = boxes.some((b) => b.checked);
    boxes[0].setCustomValidity(ok ? "" : "Pick at least one topic.");
  }

  boxes.forEach((b) => b.addEventListener("change", checkGroup));
  checkGroup(); // invalid until a box is ticked
</script>

Copy-paste ready

The HTML Checkbox example below is a complete, working form — paste it into any HTML page and it submits, no edits to the markup required.

No backend to build

Your html checkbox form posts to one endpoint. No server, PHP, or API route — accepted submissions are saved to your dashboard before owner notification email is attempted; delivery time and inbox placement depend on provider and recipient settings.

A form that really submits

Unlike a static reference snippet, this <input type="checkbox"> form actually sends data to a free splitforms backend, with spam filtering built in.

How it works

How to add HTML Checkbox to any page.

Copy the html checkbox example, drop in your free access key, and paste it into any page — submissions start landing in your dashboard.

Copy the code

Copy the HTML Checkbox example below.

Add your access key

Replace YOUR_ACCESS_KEY with a free splitforms key from the dashboard.

Paste into your site

Drop the form into any HTML page. Submissions arrive in your dashboard.

How SplitForms works

What happens after someone submits your form?

splitforms receives the submission, filters spam, saves it to your dashboard and emails you — then, on paid plans, sends it on to your webhooks and integrations. No backend infrastructure to build.

A SplitForms contact form submission launching straight to your inbox

Add your endpoint

Point your form to your unique SplitForms endpoint. That's it.

HTML form pointing at a SplitForms submit endpoint

Receive submissions

We instantly capture and organize every submission in your inbox.

Submissions inbox with searchable leads and status pills

Route anywhere

Send data to email, spreadsheets, CRMs, webhooks, and 7,000+ apps.

Generic integration tiles for email, sheets, chat, CRM, automate, and webhook

No credit card required. Set up in under 60 seconds.

Connect & automate

Where can submissions go besides email?

On paid plans, submissions can also go to Slack, Discord, Google Sheets, Notion, Airtable, Zapier or any signed webhook — and splitforms works on the platforms you build on, from WordPress and Shopify to Next.js. With Stripe connected, your forms can take payments too.

Connect your SplitForms form to Slack, Google Sheets, Mailchimp, Zapier and more
NewTake payments on your formsDeposits, bookings, order forms — submitters check out through Stripe and the money goes straight to your Stripe account. Included on every paid plan.See plans →

Setup guides for the stacks you use

Questions

HTML Checkbox questions, answered.

View all FAQs
How do I create a checkbox in HTML?

Use <input type="checkbox" name="agree" value="yes">, wrapped in a <label> so the text is clickable. Add checked to pre-tick it, and required to force it on (common for consent).

What value does a checkbox submit?

When checked, it submits its value= attribute. If value= is missing it submits "on". When unchecked, nothing is submitted for that name at all.

How do I let users select multiple options?

Give each checkbox the same name (e.g. name="interest") and a different value. Each checked box sends its own pair (interest=beta&interest=demo). Read all of them with formData.getAll("interest"). Object.fromEntries() keeps only the last one, and so does PHP's $_POST unless the name ends in [].

How do I pre-check a checkbox?

Add the checked attribute: <input type="checkbox" name="news" value="yes" checked>. It will be ticked when the page loads.

Why doesn't my unchecked checkbox submit anything?

By design — an unchecked checkbox is not included in the form data. Treat the absence of the key as the unchecked state in your backend, rather than expecting a false value.

How do I send a value when a checkbox is unchecked?

Add <input type="hidden" name="newsletter" value="no"> before the checkbox with the same name. Unchecked, only "no" is sent; checked, "no" and then "yes" are sent, and servers that keep the last value (PHP, Rails, Django) read "yes".

Is an indeterminate checkbox submitted?

Only if it is checked. indeterminate is a JavaScript property that only changes how the box looks, so the box submits by its checked state like any other checkbox: name=value when checked, nothing when unchecked. Clicking it clears the indeterminate state.

How do I require at least one checkbox in a group?

required can't do it, because it applies to a single box. Use JavaScript: while no box is checked, call setCustomValidity("Pick at least one") on the first box, and clear it with setCustomValidity("") once one is ticked.

Simple pricing

How much does splitforms cost?

Free gives you 500 submissions for $0 — no card, no time limit. Pro is $5/month for 5,000 submissions a month, and Annual is $49/year for 15,000 a month with every Pro feature.

Free

$0— 500 submissions
 

No card, no time limit

Best for testing

For side projects and indie devs.

  • 500 free submissions
  • Unlimited forms
  • Email notifications included
  • Smart spam filtering
  • Submissions dashboard
  • Redirect after submit
  • MCP server included

Annual

$49/ year
About $4.08/mo, billed yearly
Best value

Every Pro feature with triple the volume — $0.27 per 1,000 at full use.

  • 15,000 submissions / mo
  • Unlimited forms
  • Everything in Pro
  • File uploads with 5 GB storage
  • 3 team seats
  • Priority email support

No credit card required on Free • Cancel anytime • Full pricing and FAQ