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
<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
<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>
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 |
|---|---|
| Submits a value without any visible UI |
| A button that submits the form (customizable label via |
| A button that resets all form fields to their initial values |
| A generic push-button with no default form behavior; used with JavaScript |
| A submit button rendered as a clickable image |
other-input-types.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">
<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, andimagecover 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
<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
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 |
|---|---|---|
| Yes, automatically | Server-bound data tied to this specific form submission |
| 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? |
|---|---|---|---|
| No | No (not directly) | Yes |
| Yes | No | No — skipped entirely |
| Yes | No | Yes |
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
<!-- 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
<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>
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.