Passwordless

Magic Links vs OTP Codes

Both replace passwords with email. Both feel "passwordless." They are not the same product. Here's the honest comparison — UX, security, deliverability, and the situations where each one is the wrong choice.

Emilian GheoneaMay 6, 2026 8 min read

Two flavors of email-based passwordless login dominate modern auth: magic links ("we sent a link to your email, click it") and email OTPs ("we sent a 6-digit code to your email, type it here"). They look like minor variations on the same idea. They aren't. The two flows have different security models, different UX failure modes, and different operational headaches, and choosing the wrong one for your product is a quiet category of bug that shows up months after launch.

This article is the comparison we wish someone had handed us before we shipped both, in different products, and learned which one fit each one.

What each one actually is

Magic link

  1. User enters their email address.
  2. Server generates a single-use, time-limited token. Stores it (with userId, email, expiresAt, usedAt).
  3. Server sends an email containing a URL: https://app.example.com/auth/callback?token=ABC123....
  4. User opens email, clicks link.
  5. Browser hits the callback URL; server validates the token, marks it used, sets a session cookie, redirects to the app.

The user never types anything more than their email.

Email OTP

  1. User enters their email address.
  2. Server generates a short (typically 6-digit) numeric code. Stores its hash with the user ID and an expiry.
  3. Server sends the code by email.
  4. User reads the email, types the code into the original page.
  5. Server compares the hash, sets a session, lets the user in.

The user types twice (email, then code) but never leaves the page.

Rendering diagram…

The flows look similar on a diagram. The user experience is meaningfully different in three places: which tab the user ends up on, how vulnerable the flow is to interruption, and what happens when email is slow.

The "wrong tab" problem

When a user clicks a magic link, the link opens in whatever browser the email client wants to use. On a desktop, this is often the system default browser, even if the user started in a different one. On mobile, it's frequently an in-app webview embedded inside Gmail or Outlook.

The result: the magic-link click lands in a different browser context than the one the user started in. The session cookie gets set in that context. The user's original tab — the one with the half-filled form and the work they were doing — has no session.

This is the silent killer of magic-link conversion. The user clicks the link, "ends up" logged in, but isn't logged in where they were trying to be. They give up, or they get frustrated, or they log in again, this time creating a duplicate-flow mess.

OTP doesn't have this problem. The code is entered into the same tab the user started in. The session lands exactly where the user expected. The "wrong tab" failure mode does not exist for OTP.

On mobile, this difference is severe enough that we usually recommend OTP outright.

The "out-of-band" security argument

Magic-link proponents argue the flow is more secure because the user only ever interacts with the link — there's nothing to phish, nothing to type into a fake site.

This argument has merit, but it's narrower than it sounds.

A magic link is a bearer credential delivered over email. Whoever has the email has the credential. The security of the flow is bounded by the security of the user's email account. That's the same for OTP. Both flows assume email is a sufficiently strong second factor.

Where magic links can be more phishing-resistant: a user pasted into a phishing page can't easily complete the flow without going to the real email. They'd have to forward the email or copy the link out, which is awkward enough that some users would notice.

Where OTPs can be less phishing-resistant: a credible phishing page can ask for the OTP after relaying it to the real site, and the user happily types it in. Real-time OTP-relay phishing kits exist. The 6-digit code in your inbox does not by itself protect against being typed into the wrong page.

Neither is great against a sophisticated attacker. Both lose to a compromised email account. The "magic link is more secure" claim is true at the margins and shouldn't dominate the decision.

Tokens that should never be reusable

A magic link is in the URL. URLs are logged. URLs are in the user's browser history. URLs can leak through Referer headers if the destination page makes outbound requests before stripping them.

This means magic-link tokens must be single-use and short-lived. The patterns that work:

  • Token is 256+ bits of entropy.
  • Stored hashed (not raw) so a DB leak doesn't immediately give attackers working links.
  • TTL of 10-15 minutes.
  • Marked used atomically on first redemption — a second request with the same token fails.
  • Bound to a user agent or IP if your threat model justifies it (this trades security for friction; users on mobile carriers' rotating IPs hate it).

OTP tokens have a similar discipline but with a different threat model: short and numeric, so they're brute-forceable in principle, which means rate-limiting attempts is mandatory. 6 digits = 1 million combinations; without rate limiting, an attacker can grind through in seconds.

If you implement OTP without per-account, per-window attempt limits, you've built a vulnerability. The minimum:

  • 5 attempts per code, after which the code is invalidated.
  • Per-email rate limit on code generation (e.g., 1 per 30 seconds, max 5 per hour).
  • Per-IP rate limit on the verify endpoint.

Deliverability — the unglamorous deciding factor

Both flows fall apart if the email doesn't arrive within seconds. In our experience, the median time-to-inbox for transactional email is around 2-4 seconds, and the p99 is "sometimes minutes."

Magic links seem tolerant of this — the user has time to wait. In practice, they aren't, because users will close the tab while waiting and lose context. The longer the email takes, the less likely a magic link click results in a logged-in session in the right place.

OTPs are also sensitive to deliverability, but with a different failure mode: the user stares at a "enter code" page for 90 seconds, gets bored, and tries to resubmit. Now you have two valid codes, race conditions in your code-table, and a frustrated user.

Both flows benefit hugely from:

  • A reputable email infrastructure (Resend, Postmark, SES with proper warm-up). Don't try to send these from a marketing ESP.
  • SPF, DKIM, and DMARC configured correctly. If any of these are wrong, you're going to spam folders.
  • A dedicated sub-domain for transactional mail (auth.example.com or similar) so marketing engagement doesn't pull down your auth sender reputation.

If you can't make transactional email reliable, passwordless is a bad choice and you should fix that before shipping either flow.

The honest comparison

DimensionMagic linkEmail OTP
TypingEmail onlyEmail + 6-digit code
"Wrong tab" riskHigh, especially mobileNone
Phishing resistanceModerate (link harder to relay)Lower (code easily relayed)
In-page UXDisruptive (leave tab, come back)Stays in-page
Cross-device sign-inAwkward (need link in destination browser)Works (read code on phone, type on desktop)
Brute-force riskNegligible (entropy is huge)Real (must rate-limit aggressively)
Sensitivity to email delayHigh (user closes tab)Moderate (user can wait)
Implementation complexityLowerSlightly higher (rate limits, code table)

The patterns we've seen work:

  • Consumer products with a measurable funnel: OTP. The same-tab UX is worth the extra typing.
  • B2B tools, low-stakes: Magic link is fine. Users are at a desktop, in the same browser, and the flow is occasional.
  • Mobile-first apps: OTP, almost always. The wrong-tab failure mode is too costly.
  • Anything with a sensitive action (banking, transferring money): Neither alone. Use them as one factor in MFA, not as the sole credential.
  • Anything you can't make email reliable for: Neither. Passwordless without reliable email is worse than passwords.

The case for passkeys instead

If you're starting from scratch in 2026, the question worth asking is whether you should use either of these.

Passkeys (WebAuthn) are a different shape of passwordless: cryptographic keys bound to a device, with biometric or PIN unlock. They're phishing-resistant in a way magic links and OTP aren't (the credential is bound to the origin and can't be relayed). They don't depend on email deliverability. Major OS vendors back them.

The cost is a more complex enrollment, real handling of fallback (lost device, new browser), and a user education problem. Most products end up offering passkeys and an email-based fallback, which means you're still implementing magic links or OTP — just as the recovery path rather than the primary.

If you're building today, our default recommendation: passkeys as the primary, OTP as the email fallback, magic links only if you've explicitly decided the "wrong tab" tradeoff is worth it.

The smaller decisions you'll still make

Whichever you pick, you'll hit these:

  • Resend button. Required. Rate limit it. Show a countdown.
  • "Wrong email" recovery. Some flows let users edit the email on the verify screen. Be careful: changing the email mid-flow invalidates the previously sent code/link.
  • Existing-user vs new-user. Decide whether the flow signs up new users automatically or requires a sign-up step. The "magic" feel comes from a single flow; the security comes from being explicit. We've shipped both. Single-flow wins for consumer; explicit signup wins for B2B.
  • Account enumeration. If your flow says "we sent a code" only when the email exists, you've leaked which addresses have accounts. Respond identically either way.
  • Mobile keyboards. OTP inputs should be inputMode="numeric" and autocomplete="one-time-code". iOS will auto-fill from SMS or email previews if you do this right.

Each of these is a small thing. They add up. The difference between a passwordless flow that converts 90% of attempts and one that converts 60% is usually a stack of decisions like these, made deliberately versus made by default.

What to read next

The right answer is rarely the dogmatic one. Pick the flow that fits how your users actually behave, not the flow that sounds modern in a marketing page.

Written by

Emilian Gheonea

Senior Blockchain & Full-Stack Software Engineer. I build EmbedAuth — an embeddable authentication platform for SaaS — and write about the auth problems most teams hit too late.