Understanding the two one-time password algorithms — and when to use each one
Both TOTP and HOTP generate short numeric codes that can be used as a second authentication factor. They share the same underlying HMAC construction and the same Base32 secret format. The crucial difference is what drives the code change: TOTP uses time, while HOTP uses a counter. This single design decision produces very different security and usability trade-offs.
Time-based One-Time Password — RFC 6238
HMAC-based One-Time Password — RFC 4226
HOTP was defined first, in RFC 4226 (2005). It replaces the time counter used by TOTP with an integer counter that increments each time a code is generated. Both the client (authenticator device) and the server maintain their own copy of this counter.
After each successful authentication, both sides increment the counter to 43. The next login will produce a completely different code based on counter value 43.
The critical weakness of HOTP in practice is counter drift. If the user generates a code on their device but doesn't use it (for example, they pressed the button by mistake), the client counter advances but the server's counter does not. After a few such events, the two counters are out of sync and authentication fails.
To handle this, HOTP implementations typically allow a look-ahead window — the server will test the next N counter values to see if any match. This helps with occasional drift but creates a trade-off: the larger the window, the more susceptible the system is to brute-force attacks.
TOTP (RFC 6238, published 2011) replaces the counter with a time-derived value: the number of 30-second intervals elapsed since the Unix epoch. This solves the drift problem entirely — both parties independently derive the same counter from the clock without any state synchronisation, and codes expire automatically.
floor(UnixTimestamp / 30). The rest of the algorithm is identical.| Criteria | TOTP | HOTP |
|---|---|---|
| Code validity period | ~30–90 seconds | Until next use (potentially indefinite) |
| Replay attack resistance | Strong — code expires quickly | Weaker — used code stays valid until consumed |
| Phishing window | Narrow (seconds) | Wide (indefinite until next use) |
| State synchronisation | None required — stateless | Counter must be kept in sync |
| Clock requirement | Requires roughly synchronised clocks | No clock needed — fully offline |
| Lost code recovery | Automatic — wait for next window | Counter may need manual resync |
| Mobile app support | Universal — all authenticator apps | Supported but less common in mobile apps |
| Hardware token use | Possible but uncommon | Traditional hardware token standard |
| Brute-force surface | Small — code expires in seconds | Larger — especially with wide look-ahead windows |
Both TOTP and HOTP use the same otpauth:// URI scheme for QR code enrolment. The only difference is the scheme type:
// TOTP otpauth://totp/MyApp:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=MyApp // HOTP (note: also requires counter parameter) otpauth://hotp/MyApp:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=MyApp&counter=0
For the vast majority of web and mobile applications, TOTP is the right choice. It is simpler to implement correctly (no counter state to manage), more secure (short-lived codes), and universally supported by all major authenticator apps. AuthenticatorAPI.com implements TOTP.
HOTP has its place in specific scenarios:
If you are building a new 2FA system for a standard web or mobile application, TOTP is the industry standard recommendation. All major security frameworks and guidelines (NIST 800-63, OWASP ASVS) support TOTP as a valid second factor for software authenticators.