Skip to main content

UI components · Form input

OTP Input

Also called: Verification code input, PIN input, One-time code field, InputOTP

A row of small boxes for a text or email verification code, one digit per box. Typing a digit jumps to the next box. Common in sign-in, sign-up, and extra checks before sensitive actions.

Click “Labeled” to see what each part is called, or “Anti-pattern” to see the most common mistake.

How to tell AI

Swap in your own content first

Build a text-message verification page. Title: "Enter verification code." Below it, a gray line "We sent a 6-digit code to (206) •••-0142" and a "Change number" link. In the middle, 6 boxes of 48×56px with 8px gaps and 24px centered digits; the current box has a darker border and a blinking cursor. Typing a digit moves to the next box, Backspace moves back, and pasting 6 digits fills all boxes at once. On phones, show the number pad, and add `autocomplete="one-time-code"` to support autofill. When all boxes are filled, verify automatically and show loading. If the code is wrong, turn all 6 boxes red, show "That code isn't right. Try again." below, and clear them. Under the boxes, show a "Resend in 59s" countdown that turns into a clickable "Resend code" when it ends.

Send to

01Decide

Does your content look like this?

Check both columns to confirm OTP Input is what you need.

Use OTP Input when

  • Entering the code from a text or email when signing in or signing up with a phone number or email
  • An extra check before sensitive actions like changing a password, adding a bank card, or making a large payment
  • Two-factor authentication, entering the 6-digit code from an authenticator app

Pick something else when

  • Passwords or invite codes with variable length and letters. Use a regular input.

    Use insteadInput
  • CAPTCHAs or slider checks to stop bots. That's a different kind of component.

  • Long strings over 8 characters (like license keys). Boxes make them harder to type. Use a regular input with grouped formatting.

    Use insteadInput

Not sure? Upload a screenshot and page analysis will check which layout each block should use.

02Pitfalls

Common misuse

It looks like it works, but it makes things harder for users.

  1. 01

    Each box is a separate input with no paste support, so the 6-digit code copied from a text lands entirely in the first box

    The wireframe below shows this case. The red dashed box marks the problem.

  2. 02

    No resend countdown or resend button, so users who never got the text can only reload the page

  3. 03

    On a wrong code the boxes just shake, without saying whether it's wrong or expired, and nothing gets cleared

Anti-pattern, matches item 01

03Spot it

How to spot it

Look at the overall structure first, then check a few features you can spot at a glance.

Structure

A line saying where the code was sent (phone number or email), a row of 4 to 6 single-character boxes, a resend countdown, and a submit button. Errors show below the boxes.

PartsClick one to highlight it in the wireframe above

04Explained

In detail

An OTP input splits a 4- to 6-digit one-time code into a row of equal boxes, one digit each. After each digit, the cursor jumps to the next box, and Backspace goes back one. If users copy the whole code from a text message and paste it, it should fill every box at once. On phones, it should bring up the number pad and support the system's code autofill (autocomplete="one-time-code"). It usually comes with a line like "Code sent to (206) •••-0142" and a "Resend in 59s" countdown.

It only differs from a regular Input in looks and behavior. Under the hood you're still typing a string of digits, so many solid implementations use one hidden input plus a row of boxes that only display the digits. That way paste, autofill, and screen readers all just work. It's also not a CAPTCHA (typing letters from an image or dragging a slider to prove you're human). That's a different thing.

Match the number of boxes to the real code length, and make them big enough (at least 40px wide on phones). You can auto-submit when the last digit is filled, but show a loading state and block double submits. On a wrong code, turn the whole row red, say whether it's wrong or expired, and clear it so they can retry. Keep "Resend" disabled until the countdown ends, and give people a backup if the text never arrives (a voice call, or email instead).

Developer info
Term ID
component-otp-input
DOM selectors

The extension matches these CSS selectors when it inspects a page locally (tags, ARIA roles, common component library classes).

  • input[autocomplete="one-time-code"]
  • .ant-otp
  • [data-input-otp-container]
  • [data-input-otp]
  • [data-slot="input-otp"]
  • [data-slot="input-otp-group"]
  • .n-input-otp
  • .arco-verification-code
  • .van-password-input
  • .chakra-pin-input
  • .mantine-PinInput-root
  • [class*="MuiOtpInput-Box"]
Class keywords

Class names, ids and data-testid are split into words and matched in order, so page-header, PageHeader_root__x7a and pageHeader all become page, header.

  • otp-input
  • otp-inputs
  • otp
  • otp-field
  • verification-code
  • verify-code
  • code-input
  • code-inputs
  • pin-input
  • sms-code
Component names

React / Vue component names read in development mode. Case-insensitive; library prefixes such as El, Ant and Mui are dropped.

  • InputOTP
  • OTPInput
  • OtpInput
  • PinInput
  • VerificationCode
  • CodeInput
  • PinField
Structure

Computed from how the element is laid out and styled. It only adds to the score and never decides on its own.

  • form controls
  • repeated items
Priority
3 · when several match at the same level, the higher priority wins
Version
v2 · updated Sep 30, 2026