ToollyX
no sign-up Β· instant Β· free

OTP Generator

Generate standards-compliant TOTP and HOTP codes from any secret or otpauth:// URI β€” with a live QR preview and a clock-drift check most generators don't offer.

STANDARDSRFC 6238 / 4226
ALGORITHMSSHA-1 Β· SHA-256 Β· SHA-512
IMPORT/EXPORTotpauth:// URI + QR
PROCESSEDBrowser-local
728 Γ— 90 β€” Leaderboard Ad
required
Try an exampleGenerate random secret
Labels only β€” shown in an authenticator app's list after scanning. Doesn't change the generated code.
Auto-Copy on Refresh
Copies each new code to your clipboard the moment it's generated.
β†Ί Clear
One-Time Code
Scan or Copy URI
Scan with an authenticator app, or copy the URI below to import it directly.
copy otpauth:// URI
β€” β€” β€”
Refreshes in 30s Β· new code every 30s
TypeTOTP
AlgorithmHMAC-SHA-1
Digits6
Processed100% local, offline
728 Γ— 90 β€” Leaderboard Ad

How to Generate a Code

1Paste a Base32 secret or an otpauth:// URI β€” the code appears automatically, no button required for TOTP.
2Match the algorithm, digits, and period to whatever the issuing service actually specifies, if it isn't the SHA-1/6-digit/30-second default.
3Scan the QR code with a real authenticator app to confirm both sides produce identical codes.
4Code not matching? Check the Adjacent Codes panel before assuming the secret itself is wrong.

Features

RFC-compliant TOTP & HOTP
Follows RFC 6238 and RFC 4226 exactly β€” the same math real authenticator apps use.
otpauth:// URI import/export
Paste a setup URI to auto-fill every field, or copy one out to import elsewhere.
Live scannable QR code
Rendered from your current settings β€” verify against a real authenticator app instantly.
Adjacent-code clock-drift view
Previous, current, and next codes shown together β€” the fastest way to diagnose a mismatch.
Three algorithms, two digit lengths
SHA-1, SHA-256 and SHA-512, with 6 or 8-digit output, matching real-world service configurations.
Random secret generator
Generate a fresh, properly random Base32 secret for testing in one click.
HOTP counter control
Manually step the counter forward, matching how a physical hardware token actually behaves.
100% client-side
Every computation runs via the Web Crypto API in your browser β€” nothing is ever transmitted.

What's Actually Happening Behind a Six-Digit Code

A one-time code isn't random in the way a rolled die is β€” it's deterministic, derived entirely from a shared secret and a moving input (time for TOTP, a counter for HOTP) via HMAC, the same keyed-hashing primitive used throughout modern cryptography. Both the app on your phone and the server verifying your login run the identical calculation independently; because they share the same secret and (roughly) the same clock or counter position, they arrive at the same six digits without ever communicating during the login itself. That's the entire security model in one sentence β€” anyone who has the secret can compute valid codes forever, and anyone who doesn't, can't, no matter how many codes they've already seen.

TOTP vs. HOTP β€” Same Math, Different Moving Part

RFC 4226 defined HOTP first: a counter that increments by exactly one every time a code is generated and used, keeping both sides in lockstep as long as neither generates a code the other never sees. RFC 6238 adapted the identical HMAC-truncation math for TOTP, but swapped the counter for floor(currentUnixTime / period) β€” which sidesteps HOTP's synchronization fragility (a phone that generates ten codes nobody uses doesn't desync a time-based system the way it would a counter-based one) at the cost of requiring both sides to agree on the current time within a small tolerance window. This is why virtually every consumer 2FA rollout since roughly 2013 has standardized on TOTP β€” it tolerates a phone briefly losing network connectivity far better than HOTP tolerates a counter drifting out of sync.

728 Γ— 90 β€” Leaderboard Ad

Why the HMAC Runs Through the Browser's Own Crypto Engine

The actual signing step β€” turning a secret and a counter into a raw HMAC output before it gets truncated down to six or eight digits β€” runs through crypto.subtle.sign, the Web Crypto API's native implementation, rather than a hand-written HMAC routine in plain JavaScript. That matters for more than just speed: a hand-rolled cryptographic primitive is exactly the kind of code that can look correct on every test vector and still harbor a subtle timing or edge-case bug a native, browser-vendor-maintained implementation doesn't have. The same reasoning applies to the Random Secret button β€” it draws its bytes from crypto.getRandomValues, the browser's cryptographically secure random number source, not Math.random(), which is explicitly documented as unsuitable for anything security-related.

Base32 encoding and decoding, on the other hand, is genuinely just data formatting β€” no secrecy or randomness involved β€” so that part runs as plain, auditable JavaScript directly in this tool rather than needing any special API. The distinction is deliberate: use the platform's trusted crypto primitives for anything where correctness actually matters to security, and keep everything else simple and inspectable.

Diagnosing "The Code Doesn't Match" the Right Way

The instinctive reaction to a mismatched code is to assume the secret was copied wrong β€” and sometimes that's exactly it β€” but clock drift causes this far more often than people expect, especially on virtual machines, containers, and devices that have been offline for a while. Because TOTP's counter is just time divided into windows, a device even 30-40 seconds out of sync with real time will compute the adjacent window's code instead of the current one. That's precisely why this tool always shows Previous, Current, and Next side by side rather than a single value: if what you're comparing against lines up with "Previous" or "Next," the fix is checking system time, not re-entering the secret. If none of the three match, then the secret, algorithm, digit count, or period genuinely differs between the two sides β€” worth rechecking each one individually rather than guessing.

Working With the otpauth:// URI and QR Code

Every 2FA setup screen you've ever scanned encodes an otpauth:// URI into its QR code β€” the same structured format this tool both reads and writes. Pasting one in configures the secret, issuer, account label, algorithm, digit count, and period or counter in a single step, which matters most when you're reconstructing a setup from a backup you saved as plain text rather than a screenshot. Going the other direction, the QR code rendered here from your current settings is genuinely scannable by any real authenticator app β€” a fast way to confirm a custom 2FA implementation matches the standard before shipping it, without needing to hand-type a long Base32 secret into a phone keyboard.

Where This Fits Into Real Development and Recovery Work

  • Testing a 2FA implementation you're building: generate codes from the same secret your backend uses and confirm both sides agree before it ever reaches a real user.
  • Debugging a support ticket about failed logins: reproduce the exact code a user's app should be showing, and check it against the adjacent-window view for drift.
  • Recovering account access from a saved backup secret: paste it in and get working codes immediately, without waiting on a support flow.
  • Verifying a QR code before scanning it into your real authenticator app: decode and inspect the underlying secret and settings first if you're at all unsure of its source.
Verified by ToollyX Team Β· Last updated July 2026

What This Tool Isn't For

It doesn't store secrets between visits, sync across devices, or manage multiple accounts the way a dedicated authenticator app or a password manager's built-in TOTP vault does β€” every value here lives only in the current page session and disappears the moment you navigate away, by the same design principle used across every security tool on this site. If you need a permanent, secure home for 2FA secrets, use a real authenticator app or your password manager's TOTP feature; this tool is for testing, debugging, and occasional recovery, not day-to-day account protection. For generating the strong, unrelated password each account should still have alongside 2FA, see Password Generator.

Frequently Asked Questions

728 Γ— 90 β€” Leaderboard Ad