What is TOTP?

Published: 2026-09-05

How time-based one-time passwords work (RFC 6238): shared secrets, 30-second windows, HMAC, otpauth QR codes, and why generating TOTP locally keeps secrets off servers.

TOTP (Time-based One-Time Password) is the six-digit (sometimes eight-digit) code your authenticator app refreshes every 30 seconds. It is the standard behind Google Authenticator, Authy, 1Password, and most “scan this QR to enable 2FA” flows. The design is simple: you and the server share a secret; both derive the same short code from the current time without sending the secret again.

This guide explains how TOTP works, what parameters must match, how otpauth:// QR codes encode setup, and why generating or verifying codes in your browser matters when the secret is sensitive.

HOTP first, then TOTP

TOTP builds on HOTP (HMAC-based One-Time Password, RFC 4226):

  1. Take a shared secret and a counter.
  2. Compute HMAC (usually SHA-1) of the counter.
  3. Truncate the digest into a short numeric code (commonly 6 digits).

TOTP (RFC 6238) replaces the counter with a time step:

[ \text{counter} = \left\lfloor \frac{\text{Unix time (seconds)}}{\text{period}} \right\rfloor ]

With the usual 30-second period, everyone on roughly the same clock produces the same counter for that window—and therefore the same code. When the window rolls, the code changes.

Piece Typical default Notes
Secret 160 bits, shown as Base32 A–Z and 2–7 only; no 0, 1, 8, 9
Period 30 seconds Some systems use 15 or 60
Digits 6 8 is allowed but less common in consumer apps
HMAC SHA-1 SHA-256 / SHA-512 exist; many apps still expect SHA-1

If any of these disagree between the server and the app, codes will not match even when the clock is correct.

What the code actually proves

A correct TOTP code shows that the presenter knows the shared secret (or can read a device that does) and that their clock is close enough to the verifier’s. It is not a password by itself: it is a second factor layered on something you know (password) or have (session).

Clock skew is normal. Verifiers usually accept the current step plus ± one neighboring step so a few seconds of drift does not lock people out. Larger skew needs NTP fixes or a wider window—widening the window also widens the attack window for replay.

The otpauth:// URI and QR codes

Authenticator apps rarely ask you to type raw Base32 by hand. Provisioning uses a URI such as:

otpauth://totp/Issuer:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=Issuer&algorithm=SHA1&digits=6&period=30
Query / path Role
Label (Issuer:account) What the app shows in the list
secret Base32 key material
issuer Branding / grouping
algorithm, digits, period Must match the server

Encoding that URI as a QR code lets the phone import everything in one scan. Copying the URI or the raw secret is the fallback when cameras fail.

Never email a live production secret or paste it into an untrusted “QR maker” site. Prefer tools that build the URI and QR locally.

Generating and verifying without uploading the secret

Online TOTP “generators” that POST your secret to a backend create an unnecessary trust surface: the secret is the long-term credential that unlocks every future code. Prefer:

  1. Web Crypto HMAC in the browser (or a known-good CLI).
  2. No transmission of the secret, live code, or verification attempt.
  3. Parameters you can set to match a real provider (period, digits, hash).

LocalTools’ TOTP Tool does that in-tab: regenerate or paste a Base32 secret, set issuer and account, build an otpauth:// QR, watch the live code, and verify a code from your app within a ±1 step window. Nothing is stored or sent to a server.

Common pitfalls

  • Wrong hash or period — “most apps use SHA-1 / 30s”; custom IdPs sometimes do not.
  • Invalid Base32 — spaces, lowercase, or digits outside 2–7 break decoding; normalize carefully.
  • Reusing one secret across environments — treat staging and production as separate enrollments.
  • Screenshotting QR codes into tickets — the QR is the secret.
  • Assuming the code alone is auth — still require password (or another primary factor) and rate-limit guesses.

Try it in the browser

Use the TOTP Tool to:

  1. Generate a Base32 secret and set issuer, label, period, digits, and HMAC.
  2. Scan the QR with an authenticator app (or copy the URI / secret).
  3. Confirm the live code matches the app, then verify a typed code for clock-window confidence.

Related reading: Generating passwords and tokens in the browser for CSPRNG secrets, Why “local only” matters for developer tools for the privacy model, and Unix timestamps: seconds vs milliseconds for how wall-clock time feeds the TOTP counter.

All learn articles