Before you launch or pay for traffic

OTP best practices: codes that stop working

A visitor requests a code, switches to the inbox, types the digits back, and the screen says the code is wrong. A simulated visitor follows the same steps and shows which part broke.

5 visitors try to .
First test free with an accountRun it from your coding agent

What makes a one time code work for a visitor?

A one time code works when the newest code is the only valid one, the screen says so, the field accepts digits pasted with a space or dash, and the email shows the code as plain text. The code should last long enough for the visitor to switch apps, and a failed attempt should keep what was typed. A common failure is a resend: an older code is still in the inbox, and the screen does not say which one is valid. A simulated test requests a code from a working inbox, reads it there, types it back and reports the timing and the screen that answered.

What this looks like in a report

Who
Ngozi, a nurse signing up for a shift scheduling app on her phone
How they arrived
Opened the app from a link in a shift group chat
Where they stopped
Code entry screen, after the second email

“The code I typed is from the first email, and the new one has a different number. The screen does not say the new one replaced the old one, and the box rejects spaces on paste.”

The fix. Make the newest code the only valid one, and say so under the field, with a resend button that waits before it can be pressed again. Accept a code pasted with spaces or dashes, and focus the field when the screen opens.

An illustration. Run a test to see your own.See a real sample report

The visitor is holding a code that the screen no longer accepts

A code login has three moving parts: the message, the screen that asks for it, and the clock. The visitor asks for a code, waits, and when nothing shows at once they ask again. Now two emails are in the inbox, and the first looks as valid as the second. Typing the first one fails, and the screen gives no reason, so the visitor assumes the code is broken and leaves. A second problem comes from the field itself. Pasting 482 915 with a space, or a code that wraps onto two lines in the email, leaves a field that rejects input it should accept.

  • The newest code is the only valid one, and the screen says so under the field.
  • Resend waits a short while before it can be pressed again, and it shows that it is waiting.
  • The field takes digits pasted with a space or a dash, and drops the separator itself.
  • The code sits in the email as plain text, not only as an image or a link.
  • A wrong code keeps the field filled and says whether it was wrong, replaced or expired.

Which code is valid after a resend

Resend is a common trap. A visitor who waited a minute and pressed Resend has two codes in the inbox, and both look the same. Some systems invalidate the older code when the new one is created, so typing the old one fails, even though it was real a minute ago. The fix is in the words on the screen. Under the field, say that only the latest code works, and show when the latest one was sent. Add a resend control that counts down before it can be pressed again. A resend that answers with no sign that a second code is coming reads as a broken button.

Mail scanners can open a link before the visitor does

Some mail systems open each link in a message to check it before the person reads it. If the link in your message signs the visitor in or uses up the code, the scanner may spend it before the visitor taps. The visitor then sees an invalid link, and the mail looks like the fault of the app. Codes typed by hand avoid this, because nothing opens them on the visitor's behalf. Where you send a link that signs the visitor in, keep the code in the body as plain text too, and say on the screen that a link works once. Keep the code out of images, so the visitor can copy it.

The window a visitor gets, and the field they type into

A code that expires is fine if the visitor has time to use it. A visitor who switches from a mail app to the browser on a phone needs a few seconds to find the digits, and longer if the mail arrived late. Check the timing yourself: request a code, note when it arrives, wait the time your expiry allows, then try it. Also set autocomplete to one-time-code on the field, so the phone can offer the code above the keyboard. A field without that attribute makes the visitor copy each digit by hand, and each retyped digit is a chance for a typo.

Text messages and the security review stay outside this test

A simulated visitor can read a code in its inbox, so the test covers email codes. It cannot receive a text message, so a phone code path is not something it can finish. The test also does not show how well a code resists guessing, how many tries the screen allows or whether codes are stored safely. Those are security questions, and they need a review of your own. What the test does show is whether a legitimate visitor, typing a real code, gets in on the first attempt and with the message they were given.

What you get with Mimiq

  1. 01

    Run it by hand, or on every pull request

    Paste a link and a task in the app and watch the visitors work. Or run them on every preview deploy: the GitHub Action comments on the pull request, any other CI can call the MCP endpoint, and your coding agent can run it too.

  2. 02

    Bugs and usability problems in one report

    The browser records errors and failed or slow requests on the step they happened. The visitors say where the wording or the steps confused them, and where they left.

  3. 03

    Visitors that behave like your audience

    Each visitor is a different profile with a reason to be there, matched to who the page is for, described by you, or built from your own customers.

  4. 04

    A prompt to fix each problem

    Every problem comes with a fix to paste into Cursor, Claude Code, Lovable or any coding agent, and one prompt hands over the top problems at once. Then send the same visitors through again.

  5. 05

    Follow every visitor

    See each visitor's whole path, step by step with screenshots, and what it was thinking at every step. Ask any visitor a question.

The browser records relevant JavaScript errors and failed or slow app requests encountered during the run, attached to the step where they occurred. The visitors are simulated: they find problems, they do not predict how many real people will convert.

A new mail sender or template can change how codes arrive

Changing the email template, the sender domain or the mail provider changes the path a code takes. A message that arrived in seconds can start arriving late, or with a subject line visitors do not recognize. After each change, request a code from a new visitor's inbox, check the wording, and enter the digits as a visitor would. With paid credits, a test account lets visitors pass a login that sits in front of the signup flow.

Starter

Try it on one launch

$9 once
120 credits, never expire

About 4 tests of 5 visitors

  • Visitors on your landing page, signup and checkout
  • Where they left and why, with a fix to copy for each problem
  • Run it in the app or on every pull request
  • Ask any visitor a question, included
  • Test accounts and protected previews
Buy 120 credits

Builder

Test every build

$19 a month
500 credits every month

About 20 tests of 5 visitors

  • Everything in Starter
  • Credits refill each month, and what is left rolls over once
  • Cancel anytime
Choose Builder

Pro

Test every release, as a team

$49 a month
1,500 credits every month

About 60 tests of 5 visitors

  • Everything in Starter
  • Credits refill each month, and what is left rolls over once
  • Cancel anytime
Choose Pro

Scale

Test at scale, every day

$149 a month
6,000 credits every month

About 240 tests of 5 visitors

  • Everything in Starter
  • Credits refill each month, and what is left rolls over once
  • Priority support
  • Cancel anytime
Choose Scale
$0for your first test, with a free account (Google sign-in, no card). It includes 50 credits, enough for 10 visitors. After that a visitor uses 5 credits, and packs start at $9 for 120 credits.
See a sample report

Questions

Can the test check codes sent by text message?

No. A visitor cannot receive a text message, so the test covers only the email route. Check the text route yourself, with a phone you own, and never send a test code to a number that belongs to a customer.

How long should a code last?

Long enough for a real person to switch apps and type it, and short enough that an old one cannot be used later. The test does not tell you how long a real person needs. It reports whether a code arrived and whether it was still valid when typed.

Should I use a magic link instead of a code?

It depends on the device. A link opened in another browser on the same phone may fail to sign in the tab that asked for it, while a typed code works wherever the visitor types it. Test the link on a phone with the request made on a laptop, because a link that opens on another device is a common place for sign in to fail.

Does the test check whether my codes are secure?

No. It does not test how well a code resists guessing, how many attempts you allow, or how codes are stored. Those need a security review. The test shows whether a legitimate visitor gets in on the first attempt, which is a different question.

Keep reading

Send visitors and see what breaks first.

Your first test is free: sign in with Google and it starts right away. Last checked 2026-11-02.

5 visitors try to .