How does OTP work? HOTP vs TOTP vs SMS one-time passwords
A developer’s guide to one-time passwords — how HOTP, TOTP and SMS OTP are generated and verified, their trade-offs, and when to use each.
An OTP (one-time password) is a code valid for a single login or action, then discarded. It is the second factor in most two-factor authentication (2FA) flows: something you have (the code) on top of something you know (your password). There are three common ways to produce one.
The three kinds of OTP
- HOTP (HMAC-based, RFC 4226) — counter-based. Each code advances a counter shared between the device and the server.
- TOTP (time-based, RFC 6238) — the authenticator-app standard. The "counter" is the current time in 30-second steps, so codes expire on their own.
- SMS OTP — the server generates a random code and delivers it to the user's phone by SMS. No secret lives on the device.
How HOTP and TOTP are generated
Both derive the code from a shared secret with HMAC-SHA1, then truncate to 6 digits. HOTP uses a counter; TOTP uses floor(unixSeconds / 30) as that counter:
import { createHmac } from "node:crypto";
// TOTP is HOTP where the counter is the current 30-second time step.
function totp(secret, step = 30, digits = 6) {
const counter = Math.floor(Date.now() / 1000 / step);
const buf = Buffer.alloc(8);
buf.writeBigInt64BE(BigInt(counter));
const hmac = createHmac("sha1", secret).update(buf).digest();
const offset = hmac[hmac.length - 1] & 0x0f;
const code = (hmac.readUInt32BE(offset) & 0x7fffffff) % 10 ** digits;
return code.toString().padStart(digits, "0");
}
The verifier runs the same computation and compares, allowing a small window for clock drift (TOTP) or counter desync (HOTP).
SMS OTP is different
With SMS OTP there is no shared secret on the device. The server generates a random code, stores a hashed copy with a short expiry, sends the plain code by SMS, and compares the hash when the user types it back. That is the flow Eveses powers on the receiving side — receive the OTP via API on a real number, no SIM.
HOTP vs TOTP vs SMS — trade-offs
| HOTP | TOTP | SMS OTP | |
|---|---|---|---|
| Based on | Counter | Time (30s) | Random server code |
| Secret on device | Yes | Yes | No |
| Works offline | Yes | Yes | No |
| Main weakness | Counter desync | Clock drift | SIM swap / SS7 |
| Best for | Legacy tokens | Authenticator apps | Onboarding, reach, no-app |
When to use which
- TOTP for app-based 2FA where users can install an authenticator.
- SMS OTP for onboarding and the widest reach — nearly everyone has a phone and no app is needed. It is weaker against SIM-swap, so pair it with rate limiting and fraud checks for sensitive actions.
- HOTP mainly for legacy hardware tokens.
Receiving SMS OTPs programmatically
To test or automate SMS OTP flows across countries you need a real number you can read the code from. See live pricing by country and the OTP API.
Ready to build? Create a free Eveses account, top up a wallet, and grab your API key — no KYC. See the API docs or live pricing.