HTMLHidden & Other Inputs

Hidden and Other Inputs

<input type="hidden"> submits a name/value pair along with the rest of the form without rendering any visible control on the page. It's how forms pass along data the user doesn't need to see or edit, but that the server still needs when the form is submitted.

Passing Data Without Displaying It

hidden-basic.html

HTML
<form action="/orders/update" method="post">
  <input type="hidden" name="order-id" value="ORD-48213">

  <label for="quantity">Quantity</label>
  <input type="number" id="quantity" name="quantity" value="1" min="1">

  <button type="submit">Update Order</button>
</form>

Here, the visible part of the form only lets the user change the quantity — but the server also receives order-id, telling it which order to update, without cluttering the UI with a field the user shouldn't be editing.

Common Use Cases

Use case

Why hidden input helps

CSRF tokens

A per-session or per-form token the server generated, needed to verify the request came from a legitimate form

Record/entity IDs

Tells the server which database row a form edit applies to

Referrer or campaign tracking

Carries a value like a referral code from page load through to form submission

Redirect targets

Tells the server where to send the user after processing the form

csrf-token-example.html

HTML
<form action="/settings/update" method="post">
  <input type="hidden" name="csrf_token" value="a1b2c3d4e5f6...">

  <label for="display-name">Display name</label>
  <input type="text" id="display-name" name="display-name">

  <button type="submit">Save</button>
</form>
Hidden isn't secret
A hidden input is invisible in the rendered page, but its name and value are still plainly visible in the page source, in browser dev tools, and in the raw HTTP request when the form submits. Never put anything sensitive — passwords, secret keys, unencrypted personal data — in a hidden input. Anyone can open dev tools and change its value before submitting, too, so the server must still validate that value rather than trusting it blindly.
CSRF tokens are safe precisely because they're single-use/verifiable
A CSRF token in a hidden input isn't a secret meant to be kept from the user — it's a value the server can verify came from a form it actually rendered, protecting against cross-site request forgery. Its safety comes from server-side verification, not from being hidden.
Other Input Types Worth Knowing

Beyond the well-known text/number/date families, HTML defines a handful of other input types that don't fit neatly elsewhere but are useful to know about.

Type

Purpose

hidden

Submits a value without any visible UI

submit

A button that submits the form (customizable label via value)

reset

A button that resets all form fields to their initial values

button

A generic push-button with no default form behavior; used with JavaScript

image

A submit button rendered as a clickable image

other-input-types.html

HTML
<input type="submit" value="Place Order">
<input type="reset" value="Clear Form">
<input type="button" value="Preview" onclick="showPreview()">
<input type="image" src="/pay-button.png" alt="Complete payment">
Prefer <button> over input type=submit/button today
Modern markup generally prefers <button type="submit"> and <button type="button"> over their <input> equivalents, since <button> can contain rich content (icons, nested markup) instead of only a plain-text value.
  • Use type="hidden" to submit data the user shouldn't see or edit directly.

  • Hidden values are still fully visible in page source and dev tools — never store secrets there.

  • The server must still validate any hidden value, since a user can edit it before submitting.

  • submit, reset, button, and image cover other non-text input behaviors, though <button> is often preferred today.

Updating a Hidden Value With JavaScript

Hidden inputs aren't limited to a fixed value set at page load — JavaScript can update them right before submission, which is a common way to pass computed client-side state (like a timezone offset or a selected filter combination) to the server without adding visible fields.

hidden-updated-by-js.html

HTML
<form id="checkout-form" action="/checkout" method="post">
  <input type="hidden" id="client-timezone" name="client-timezone">
  <button type="submit">Continue to Payment</button>
</form>

set-hidden-value.js

JS
const timezoneField = document.getElementById('client-timezone');
timezoneField.value = Intl.DateTimeFormat().resolvedOptions().timeZone;
Hidden Inputs vs data-* Attributes

Both hidden inputs and data-* attributes can attach extra information to markup, but they serve different purposes. A hidden input's value is automatically included when the form submits. A data-* attribute is just metadata sitting on an element for JavaScript to read — it is never submitted with a form on its own.

Mechanism

Included in form submission?

Typical use

<input type="hidden">

Yes, automatically

Server-bound data tied to this specific form submission

data-* attribute

No — must be read and added by JavaScript if needed

Client-side metadata for scripting/styling hooks

Hidden Inputs and Disabled Fields

A related gotcha: a form field with the disabled attribute is not submitted at all — the browser skips it entirely, unlike hidden inputs which always submit. If you want a field to be visible-but-uneditable while still submitting its value, use readonly instead of disabled, or fall back to a hidden input holding the same value.

State

Visible?

Editable?

Submitted with form?

type="hidden"

No

No (not directly)

Yes

disabled

Yes

No

No — skipped entirely

readonly

Yes

No

Yes

readonly vs disabled
Reach for readonly when a value must still be submitted but shouldn't be editable in the current context (e.g. a pre-filled email during a multi-step signup). Reach for disabled only when the field's value genuinely shouldn't be part of the submission at all.
Multi-Step Forms: Carrying State Between Steps

Hidden inputs are the classic way to carry data forward across a multi-step, server-rendered form, where each step is its own page submission rather than a single-page JavaScript app.

multi-step-form.html

HTML
<!-- Step 2 of a checkout flow: keeps step 1's data alive -->
<form action="/checkout/step-3" method="post">
  <input type="hidden" name="shipping-address" value="123 Main St, Springfield">
  <input type="hidden" name="cart-id" value="CART-9931">

  <label for="payment-method">Payment method</label>
  <select id="payment-method" name="payment-method">
    <option value="card">Credit Card</option>
    <option value="paypal">PayPal</option>
  </select>

  <button type="submit">Continue</button>
</form>
Hidden Inputs for Analytics and A/B Testing

Marketing forms often carry a hidden field recording which page variant, campaign, or referral source a visitor arrived from, so that information reaches the backend alongside the actual form data.

analytics-hidden-field.html

HTML
<form action="/signup" method="post">
  <input type="hidden" name="utm_source" value="newsletter">
  <input type="hidden" name="ab_variant" value="hero-b">

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

  <button type="submit">Sign Up</button>
</form>
Don't trust client-supplied hidden values for anything security-critical
A user can open dev tools and change utm_source or an order-id before submitting. That's fine for analytics (worst case: mislabeled data), but never use an editable hidden field to determine something like a price, a discount amount, or a permission level — recompute or re-verify those values server-side.