splitforms.com
← Back to the journal

HTML Autocomplete Attribute: Form Autofill Done Right

How the HTML autocomplete attribute works: every standard token (name, email, tel, address), browser autofill behavior, accessibility wins, and testing tips.

Start free — 500 submissions/moSee pricing →No credit card. Paid plans from $5/mo.

How browser autofill decides what to fill

Every major browser ships two separate autofill engines: one for form data (names, addresses, phone numbers) and one for passwords. Both engines start by reading the autocomplete attribute on each field. When it's present and matches a token the browser recognizes, that's the strongest possible signal — the browser knows exactly what kind of value belongs there, independent of the field's name, id, placeholder, or visible label text.

When autocomplete is missing, browsers fall back to heuristics: pattern-matching the name attribute against common strings (fname, email_address, phone1), reading the nearest <label>, and even looking at placeholder text. Heuristics work most of the time on a well-labeled form, but they're guesses — a field named contact could be an email or a phone number, and the browser has to pick one. An explicit token removes the guesswork entirely.

The other thing autofill checks is field visibility and type. A field with type="hidden", display: none, or zero size is generally excluded from autofill — browsers try not to fill data into fields a human can't see, precisely because that pattern has been abused to silently harvest saved data (more on that below). Autofill also respects the page's form boundaries: fields outside a <form>, or in a different form on the same page, aren't grouped together.

Complete autocomplete token reference

The HTML Living Standard defines a fixed vocabulary of autocomplete tokens grouped by what they describe. Here's the practical subset that covers essentially every contact, signup, or checkout form.

Identity tokens

TokenFieldNotes
nameFull name, single fieldUse when you have one "Full name" input, not split first/last.
given-nameFirst namePair with family-name when the form splits the name.
family-nameLast nameSome locales (many East Asian names) don't map cleanly to given/family — consider a single name field if your audience is global.
emailEmail addressPair with type="email" for validation and the right mobile keyboard.
telPhone number, single fieldPair with type="tel". Use the split tel-* tokens only if you actually split the input into parts.
organizationCompany or organization nameCommon on B2B contact and demo-request forms.
organization-titleJob titleRarely autofilled but still improves heuristic matching.

Address hierarchy

TokenFieldNotes
street-addressFull street address, single multi-line fieldUse for a single free-text address <textarea>.
address-line1Street address, line 1Use instead of street-address when you split the address into separate lines.
address-line2Apartment, suite, unitOptional. Leave unrequired.
address-level2City / townThe standard token — most browsers still match a field simply labeled "City" correctly.
address-level1State / province / regionChrome and Safari fill this from the saved address profile's region.
postal-codeZIP / postal codeUse inputmode="numeric" alongside it for a numeric keyboard on mobile without changing type.
countryCountry, ISO 3166-1 alpha-2 codeFor a <select> with two-letter option values (US, GB, DE).
country-nameCountry, full nameFor a text field or a <select> with full country names instead of codes.

Payment tokens (rarely needed on contact forms)

The spec also defines cc-name, cc-number, cc-exp, cc-exp-month, cc-exp-year, and cc-csc for credit card fields. A standard contact, lead-gen, or newsletter form never needs these — collecting card numbers through a plain HTML form instead of a PCI-compliant payment processor (Stripe Elements, Checkout) is a compliance and security liability, not just an autofill question. Only reach for the cc-*tokens if you're building a form on top of an actual payment SDK that mounts real card fields.

One-time codes

autocomplete="one-time-code" is the token for SMS or authenticator verification codes. Safari, Chrome, and Android's autofill service all recognize it and offer to insert a code parsed directly out of an incoming text message — no app-switching, no copy-paste. Use type="text" with inputmode="numeric" rather than type="number", since a code can have leading zeros a numeric input would strip.

Why autocomplete="off" gets ignored (and what to do instead)

It's a common assumption that autocomplete="off" stops browsers from filling a field. It doesn't — not for the fields where it would matter most. Chromium's bug tracker documents the decision explicitly: too many sites set autocomplete="off" on login and address fields just to look "clean," and that broke password managers for millions of users. So Chrome, Firefox, and Safari all deliberately override off on fields they classify as login, address, or payment fields, filling them anyway based on their own heuristics.

Where autocomplete="off" doesstill work is on fields the browser doesn't recognize as a standard type — a genuinely one-off numeric code, an internal reference ID, a field that should never be remembered because its value is unique per visit. Even then, browser support is inconsistent enough that you shouldn't depend on it for anything security-sensitive.

The honest workarounds, in order of how often you actually need them:

  • Usually: just let it autofill. If a field maps to a real-world value like name or email, autofill is a feature for your visitor, not a bug. Fighting it costs you conversion for no security benefit — server-side validation should reject bad data regardless of where it came from.
  • For a field that should start empty every time (a "referral code" that shouldn't carry over from a previous session), give it a dynamic, randomized name attribute per page load, or generate the field with JavaScript after page load rather than in the static HTML. Browsers autofill based on stable name/token pairs seen across visits, so removing that stability removes the match.
  • For a genuine one-time code field, use autocomplete="one-time-code" deliberately — you want the browser to fill it, just from the right source (an incoming SMS), not from a stale saved value.
  • Never use autocomplete="off" as a security control. If a field is sensitive, protect it server-side (rate limiting, CSRF tokens, HTTPS). Autofill suppression is not an access control and every major browser treats it as advisory at best.

Autofill vs. JavaScript validation pitfalls

Browser autofill inserts values in a way that doesn't always trigger the DOM events your validation code is listening for. This is the single most common "my form looks empty but the browser filled it" bug report.

  • The event gap. Some browsers fire input and change events when autofilling a field, others don't reliably fire them the same way React's synthetic event system expects — particularly for controlled inputs whose value is driven by state. If your submit button stays disabled after the browser visibly fills every field, this is almost always why.
  • The fix for vanilla JS or framework code that reads on submit: read form.elements or FormData directly at submit time instead of relying on cached state from earlier keystroke events. A submit-time read always sees the current DOM value, autofilled or typed.
  • The fix for React/controlled inputs: validate :autofill-aware, or simply re-validate in the submit handler rather than only on onChange. See how to validate an HTML form with JavaScript for the full pattern, including the submit-time re-check that catches autofilled values React's controlled-input state missed.
  • Don't validate on every keystroke for autofilled fields. A field that goes from empty to fully filled in one browser action can trip "too fast, must be a bot" heuristics if you've built naive timing-based validation. Autofill is a legitimate, fast, human-initiated action.

Styling autofilled fields

Chrome and Safari apply a forced yellow (or light blue, depending on OS theme) background to autofilled fields by default, which clashes with most custom form designs. You can't remove it with background-color directly — WebKit ignores that on autofilled inputs — but you can override it with the vendor-prefixed autofill pseudo-class:

/* Override the forced autofill background in Chrome/Safari (WebKit) */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  /* box-shadow trick: a huge inset shadow paints over the
     browser's forced background without touching background-color */
  -webkit-box-shadow: 0 0 0 1000px #ffffff inset;
  -webkit-text-fill-color: #111111;
  transition: background-color 5000s ease-in-out 0s;
}

/* Standardized :autofill (Baseline 2023+, Firefox/Safari/Chrome) */
input:autofill {
  box-shadow: 0 0 0 1000px #ffffff inset;
}

The box-shadow inset trick is the standard workaround because it paints on top of the browser's forced background rather than trying to unset it. The :autofill pseudo-class (without the -webkit- prefix) is now Baseline-supported across current Chrome, Firefox, and Safari, so include both for maximum coverage of visitors on older browser versions.

Password managers and one-tap fill on iOS/Android

Correct autocompletetokens don't just help built-in browser autofill — they're what third-party password managers (1Password, Bitwarden, Dashlane) and the OS-level autofill services on iOS and Android key off of. On mobile specifically, this is where the biggest conversion win lives: a visitor filling out a contact form on their phone can tap the keyboard's autofill suggestion bar and populate name, email, and phone in three taps instead of typing on a small keyboard.

  • iOS Safari reads autocomplete tokens to populate the QuickType bar above the keyboard with contact-card data (Contacts app) or saved credentials.
  • Android Chrome uses Google's Autofill Service, which also honors standard tokens, plus its own on-device heuristics as a fallback.
  • Third-party password managers on both platforms register as system-level autofill providers and read the same autocomplete attributes — there's no separate API to target them specifically. Get the standard tokens right and you get every autofill provider for free.

The practical takeaway: don't treat autocomplete tokens as a Chrome-only or desktop-only optimization. Mobile is where typing friction is highest and where correct tokens save the most time per field.

section-* scoping and shipping/billing prefixes

When a single form has more than one instance of the same logical field — most commonly a shipping address and a billing address on one page — a bare autocomplete="address-line1" on both fields is ambiguous. The browser can't tell which block is which, and may fill both with the same saved address. The spec solves this with space-separated prefixes, applied in this order: section-* (optional, for multiple forms of the same type on one page), then shipping or billing, then the field token.

<!-- Shipping address block -->
<input name="ship_line1" autocomplete="shipping address-line1">
<input name="ship_city"  autocomplete="shipping address-level2">
<input name="ship_zip"   autocomplete="shipping postal-code">

<!-- Billing address block -->
<input name="bill_line1" autocomplete="billing address-line1">
<input name="bill_city"  autocomplete="billing address-level2">
<input name="bill_zip"   autocomplete="billing postal-code">

<!-- Two separate contact forms on the same page (e.g. "Contact sales"
     and "Contact support") — section-* keeps their autofill separate -->
<input name="sales_email"   autocomplete="section-sales email">
<input name="support_email" autocomplete="section-support email">

For a typical single-purpose contact form, none of this is necessary — a plain email or address-line1 token is all you need. Reach for the prefixes only when the same page genuinely repeats a field type in more than one logical group.

Full example: a contact form with correct autocomplete tokens

Here's a complete, working contact form with every field tagged for autofill, submitting to a form backend endpoint:

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

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

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

  <label for="phone">Phone</label>
  <input
    type="tel"
    id="phone"
    name="phone"
    autocomplete="tel"
  >

  <label for="company">Company</label>
  <input
    type="text"
    id="company"
    name="company"
    autocomplete="organization"
  >

  <label for="address">Street address</label>
  <input
    type="text"
    id="address"
    name="address_line1"
    autocomplete="address-line1"
  >

  <label for="city">City</label>
  <input
    type="text"
    id="city"
    name="city"
    autocomplete="address-level2"
  >

  <label for="zip">ZIP / postal code</label>
  <input
    type="text"
    id="zip"
    name="postal_code"
    autocomplete="postal-code"
    inputmode="numeric"
  >

  <label for="message">Message</label>
  <textarea
    id="message"
    name="message"
    autocomplete="off"
    required
  ></textarea>

  <!-- Honeypot: bots fill every visible-looking field, humans never see it -->
  <input type="checkbox" name="botcheck" style="display:none">

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

Note the message field is the one legitimate place for autocomplete="off" — free-text message content is never something a visitor wants auto-filled from a previous submission, and browsers generally respect off on fields they don't recognize as a standard identity or address type. The access_key hidden field stays static and untouched by autofill; see the HTML input reference for the full list of input types and attributes.

Security: hidden-field autofill harvesting

A known attack pattern abuses autofill to exfiltrate more data than a visitor intends to share. The setup: a form has a visible field (say, a newsletter signup asking only for email) plus additional fields for name, phone, and address that are visually hidden with CSS (opacity: 0, positioned off-screen, or a zero-size box) but still tagged with recognizable autocompletetokens and still technically part of the form. If a browser fills those hidden fields anyway, the site captures the visitor's full autofill profile from a form that only asked for one thing.

Modern browsers have hardened against this — Chrome and Firefox both exclude fields with zero dimensions or visibility: hidden from autofill, and treat display: none fields as non-fillable. But the defense isn't airtight across every browser version and CSS technique, so don't rely on the browser to protect you here. The rule for your own forms: never include a field in the DOM that you don't intend the visitor to see and fill. If you need a decoy honeypot field for spam protection, give it a generic, non-identity name (not email or phone) and no autocomplete token at all, so it never becomes an unintentional data-harvesting surface.

Accessibility and conversion benefits

WCAG 2.1 Success Criterion 1.3.5 (Identify Input Purpose, Level AA) requires that the purpose of common input fields be programmatically determinable — not just visible in a label, but readable by software. On the web, the recognized way to satisfy this is the autocompleteattribute set to one of the standard tokens covered above. This isn't a nice-to-have: sites targeting WCAG 2.1 AA conformance (a common legal and procurement bar) need it on every name, email, phone, and address field.

The accessibility win compounds for users with cognitive or motor disabilities, who benefit disproportionately from not having to re-type information they've entered elsewhere. It also helps screen-reader and voice-control users, whose assistive tools can use the same purpose metadata to describe or navigate a field more precisely than generic label text alone provides.

On the conversion side, the mechanism is simple: every field a visitor doesn't have to type by hand is a field that can't be mistyped, abandoned mid-entry, or skipped out of friction. Mobile visitors in particular convert better when a form can be completed in a handful of taps instead of a full manual entry — and that's exactly what correct autocomplete tokens unlock. See contact form conversion rate benchmarks and fixes for the broader picture of what moves completion rate beyond autofill.

Testing autofill across browsers

Autofill behavior is genuinely inconsistent across browsers and platforms, so test on real devices where possible, not just desktop Chrome:

  • Chrome desktop — go to chrome://settings/addresses and chrome://settings/passwords to add test profiles, then click into each field to confirm the suggestion dropdown offers the right value.
  • Chrome DevTools — the Autofill panel (under the "More tools" menu, or via the Elements panel's autofill inspection) shows exactly which token each field was matched to and why, which is the fastest way to debug a field that isn't filling.
  • Safari desktop and iOS — test with a Contacts card and a saved address under Safari > Settings > AutoFill (macOS) or Settings > Safari > AutoFill (iOS). iOS Safari's QuickType bar is the most visible real-world test.
  • Android Chrome — check Chrome > Settings > Autofill and payment methods, plus the system-level Autofill Service under Android Settings > System > Languages & input > Advanced > Autofill service, since Android can route autofill through a third-party password manager instead of Chrome's own store.
  • Firefox — Settings > Privacy & Security > Forms and Autofill. Firefox's address/credit-card autofill is less aggressive than Chrome's by default and may need to be enabled.
  • Always test with a genuinely populated profile. An empty test profile makes every autocomplete field look identical (nothing fills), which hides token mismatches. Fill in a full name, email, phone, and address once per browser and reuse that profile for every test pass.

FAQ

What does the HTML autocomplete attribute do?

The autocomplete attribute tells the browser what kind of data a form field expects — a name, an email, a street address — using a standard set of tokens. Browsers and password managers use that hint to offer or auto-fill matching saved data, which speeds up form completion and cuts typos on mobile.

Why doesn't autocomplete="off" stop autofill?

Chrome, Firefox, and Safari intentionally ignore autocomplete="off" on login and address-type fields — Chromium's own tracker (crbug.com/468153) documents the decision, made because too many sites misused it to block password managers, hurting users. Browsers still respect it on genuinely one-off fields like verification codes typed once and never reused.

What autocomplete value should I use for a phone number field?

Use autocomplete="tel" for a single international-format phone field. If you split it into parts, use tel-country-code, tel-area-code, and tel-local for the segments. Avoid tel-national alone unless you're certain every visitor's country code is fixed and known.

Do I need separate autocomplete tokens for shipping and billing addresses?

Yes, if a form has both. Prefix the token with shipping or billing inside a space-separated value, e.g. autocomplete="shipping address-line1" and autocomplete="billing address-line1". Without the prefix, browsers can't tell which address block a field belongs to and may fill both with the same data.

Does the autocomplete attribute help accessibility?

Yes. WCAG 2.1 Success Criterion 1.3.5 (Identify Input Purpose, Level AA) requires that common input purposes be programmatically determinable, and the standard way to satisfy it on the web is the autocomplete attribute with a recognized token. It also lets assistive technology and browser extensions pre-fill or describe fields more accurately for users with cognitive or motor disabilities.

Can autocomplete tokens improve conversion rate?

Indirectly, yes. Correct tokens let browsers and password managers one-tap fill an entire form, which shortens time-to-submit and reduces abandonment from typos — especially on mobile, where typing an email or address by hand is the single biggest source of form friction.

What autocomplete value works for a one-time password or verification code?

Use autocomplete="one-time-code". Safari, Chrome, and Android all recognize it and will offer to auto-fill a code from an SMS message directly into the field, without the user needing to switch apps or copy-paste.

Should hidden fields ever use autocomplete?

No — never rely on autocomplete to populate a hidden field with sensitive data. Some older mobile browsers have filled visually hidden but still-focusable fields, which attackers have used to harvest saved autofill data the visitor never meant to submit. Keep truly hidden fields (like an access_key) static, not autocomplete-driven, and never overlap a visible field's name with a decoy honeypot field that shares an autocomplete token.

More reads: validating an HTML form with JavaScript, contact form conversion rate benchmarks, HTML input reference, plain HTML contact form, free contact form backend, pricing, or all posts.

Related articles

More practical guidance from guides.

Browse the journal →
Guides

Elementor Form Not Sending Email? 5 Fixes That Work (2026)

Why Elementor form notifications never arrive: the wp_mail root cause, how to confirm it in

8 min readRead →
Guides

Why mailto: Doesn't Work as a Form Action (and What Converts 3–10× Better)

Using action="mailto:you@example.com" opens the visitor's mail app instead of sending anythi

6 min readRead →
Guides

Why Your Form Works in Preview but Not on the Live Site

Form submits perfectly in your builder's preview but fails in production? The usual causes:

7 min readRead →

Explore this topic

Start with the overview, then move into focused guides.

OverviewContact Forms for Every FrameworkStart here →GuideContact Form for Next.jsRead →GuideContact Form for ReactRead →GuideContact Form for VueRead →ReferenceContact form guideOpen →

Building forms with ChatGPT, Claude, Cursor, or v0? Connect the native MCP server and give your agent a production form backend.

Explore the MCP server →

Give your form a production backend.

One endpoint adds delivery, spam filtering, storage, and integrations. Start with 500 submissions a month for free.

Create free accountRead the docs →
Secure checkoutSSL encryptionPrivacyProtected
VISAAMERICANEXPRESSstripe