TOTP / 2FA Code Generator

Free online TOTP / 2FA code generator (RFC 6238). Paste a Base32 secret to see the current and next codes, scan the QR with Google Authenticator, and verify your setup.

000 000
--s
Next code:
Account & Algorithm
Paste a Base32-encoded secret. Letters A–Z and digits 2–7, padding optional. Click the dice icon to generate a random 20-byte secret.
Scan with Authenticator

TOTP / 2FA Code Generator (RFC 6238)

Generate Time-based One-Time Passwords (TOTP) entirely in your browser. Paste any Base32 secret — the kind Google Authenticator, Authy, Microsoft Authenticator, and 1Password import — and see the live 6-digit code, the next code, a countdown ring, an otpauth:// URI, and a QR code you can scan with any authenticator app. Implements RFC 6238 exactly, verified against all six official test vectors. Useful for debugging 2FA setups, validating server-side code generation, or running a fully offline authenticator.

What is TOTP and how does it differ from HOTP?

TOTP (Time-based One-Time Password, RFC 6238) generates a 6-to-8-digit code that changes every 30 seconds. It is the algorithm behind Google Authenticator, Microsoft Authenticator, Authy, 1Password's built-in OTP, FreeOTP, and dozens of other apps.

It builds on HOTP (HMAC-based One-Time Password, RFC 4226):
- HOTP uses a counter that increments by 1 each time you press a button or use a code.
- TOTP uses the current Unix time divided by a period (30s by default) as the counter. So at T = floor(time / 30) the value of the code is identical for everyone with the same secret.

Both produce a code by computing HMAC(secret, counter) and truncating the result. TOTP is more practical because no synchronisation between client and server is needed beyond reasonably accurate clocks (NTP-grade is enough).

What does this tool actually compute?

Exactly what RFC 6238 specifies — verified against the official test vectors in Appendix B:

1. Decode the Base32 secret to raw bytes.
2. Compute counter = floor(unix_time / period) and pack it as 8-byte big-endian.
3. Compute HMAC over those 8 bytes using the chosen algorithm (SHA-1, SHA-256 or SHA-512) and the secret.
4. Dynamic truncation: take the last 4 bits of the HMAC, use them as an offset, read 4 bytes starting at that offset, mask the top bit.
5. Output (bin % 10^digits), zero-padded to the chosen width.

The HMAC step uses the browser's Web Crypto SubtleCrypto, so the cryptography is native and audited; this tool only wires up the protocol around it. Six RFC test vectors (T = 59, 1111111109, 1111111111, 1234567890, 2000000000, 20000000000) all match the expected output.

How do I add a new account to Google Authenticator using this tool?

Two paths, depending on which side you control:

1. You have a service that produced a secret (showed you a string or a QR). Paste the Base32 secret into the Secret field, optionally fill in 'Account label' (e.g. [email protected]) and 'Issuer' (the site name) so your authenticator displays a meaningful label. The tool will show you the current code so you can compare against the service's verification step.

2. You're building a service and need to enrol a user. Click the dice icon to generate a random 20-byte Base32 secret, fill in 'Account label' and 'Issuer'. The QR encodes a standard otpauth:// URI — your user scans it in their authenticator app and starts producing matching codes immediately. Copy the otpauth:// URI to embed it in your own QR code, or download the rendered QR PNG.

In both flows the codes are produced locally — never transmitted — so it's safe to use even for production secrets.

Is it safe to paste my real 2FA secret here?

Technically yes — everything runs in your browser — but a Base32 TOTP secret is the master credential for your 2FA. Anyone who learns it can produce the same codes you do. So apply the same care you would to a password:

- Don't paste it in browsers you don't trust (kiosks, shared machines, browsers with untrusted extensions installed).
- Inspect DevTools → Network to confirm the secret is never POSTed. It isn't — but the option to confirm is right there.
- Don't keep the page open in a tab where someone else can read the value.
- For most users, the right reason to use this tool is testing or recovering from a backup (e.g. you saved the secret from a service's setup screen and lost the authenticator app); not as a daily replacement for a hardware key.

If you generate a random secret with the dice button, it's safe to share that test secret freely — but treat any secret tied to a real account like a password.

What is the format of the otpauth:// URI?

RFC-style URI used by all major authenticator apps:

otpauth://totp/Issuer:[email protected]?secret=BASE32SECRET&issuer=Issuer&algorithm=SHA1&digits=6&period=30

Fields:
- The 'path' after totp/ is the label, usually 'Issuer:Account'. The Issuer prefix is optional but recommended; both copies should match the issuer query parameter.
- secret: Base32, no padding, uppercase preferred.
- issuer: human-friendly service name (URL-encoded).
- algorithm: SHA1 (default), SHA256, or SHA512. Many apps only support SHA1.
- digits: 6 (default), 7, or 8. Many apps only support 6.
- period: 30 (default) seconds. Some apps allow 60.

This tool only adds non-default parameters to keep the URI clean. Authenticators tolerate extra parameters but the default-omitted form is the most portable.

Why is the code in the authenticator app sometimes one step off?

TOTP depends on both ends having a close-enough clock. If your device's clock drifts by more than a few seconds, your generated code will compute against a different time-step than the server.

How services and clients handle this:

- Servers typically accept the previous and next code in addition to the current one. That gives a ~±30 s tolerance window.
- Clients should run NTP. On Android, 'Use network-provided time' must be on; on iOS, 'Set Automatically' under Date & Time; on Linux/macOS, systemd-timesyncd or chrony will keep the clock within milliseconds of NTP servers.
- Authy and Google Authenticator both offer an in-app time-sync button to fetch network time without changing the system clock.

This tool uses your local system clock (whatever your browser reports as Date.now()). If both clocks are right, the codes match; if either is wrong by more than 60 seconds, you'll see a mismatch.

Which algorithms and digit lengths should I pick?

Defaults are SHA-1, 6 digits, 30 s period. Reasons to deviate:

- SHA-1: the universal default. Every authenticator app supports it. Recommended unless you have a specific reason to change.
- SHA-256 / SHA-512: stronger HMAC. Useful when both the issuing server and client app support it (Authy and 1Password do; some older Google Authenticator versions don't render codes correctly with SHA-256+).
- 6 digits: universally supported, ~1 in a million guess probability per attempt.
- 7 / 8 digits: stronger; Yubico OATH supports them; many app authenticators only show 6.
- 30 s period: standard. 60 s reduces the rate of new codes but makes server-side replay protection easier; 15 s is uncommon and breaks some apps.

For compatibility, stick to SHA-1 / 6 / 30. For internal tools where you control both sides, SHA-256 / 6 / 30 is a reasonable upgrade.

Where does the data go? Can I use this offline?

Your secret never leaves the browser. The generator runs entirely client-side:

- HMAC is computed via window.crypto.subtle, the same primitives used by HTTPS in your browser. No JavaScript implementation of SHA-1 is bundled.
- The QR rendering uses the qrcode library loaded once from a public CDN (cdn.jsdelivr.net). After that load, the page works offline — including code generation. Disconnect Wi-Fi and watch it keep ticking.
- No analytics is performed on your inputs. You can confirm by opening DevTools → Network while typing; only static asset requests appear.
- The 'Copy code' and 'Copy URI' buttons write to your local clipboard. The 'Download QR' button creates an in-memory PNG and triggers a local save.

For maximum offline use, load the page once on a trusted machine, then disable the network. The HMAC, base32 decode, QR render, and clipboard all keep working — useful for air-gapped server setups or recovery scenarios.

Key Features

  • RFC 6238 compliant, verified against all six official test vectors
  • HMAC via the browser's native Web Crypto API (no JS crypto bundled)
  • Supports SHA-1, SHA-256 and SHA-512
  • Configurable digits (6 / 7 / 8) and period (15 / 30 / 60 seconds)
  • Live updating display of the current and next code
  • Animated countdown ring shows the seconds remaining in the current step
  • Random 20-byte Base32 secret generator using crypto.getRandomValues
  • Compatible otpauth:// URI for Google Authenticator, Authy, 1Password, Microsoft Authenticator and more
  • Generates a QR code that scans cleanly in every major authenticator app
  • Show / hide toggle on the secret field
  • Copy code or otpauth URI to clipboard with one click
  • Download the QR code as a PNG image
  • Account label and issuer fields for friendly authenticator entries
  • 100% client-side — your secret never leaves the browser
  • Works offline after the first page load