Standards/otpauth-uri
otpauth URI
Overview
The otpauth URI is a URI payload format that carries the provisioning data for a one-time-password (OTP) authenticator credential — the shared secret plus its parameters — so that a 2FA app can enrol an account by scanning a single qr-code. The format originates from Google's Google Authenticator project, whose "Key Uri Format" wiki page is the de facto specification.[1] The basic structure is otpauth://TYPE/LABEL?PARAMETERS, where TYPE is either totp (time-based) or hotp (counter-based), distinguishing the two OTP algorithm families.[1] An expired IETF individual Internet-Draft, Usage specification of the otpauth URI format for TOTP and HOTP token generators, exists to document the de facto schema, but carries no formal IETF standing.[2]
History
The otpauth URI was introduced by Google's Google Authenticator app; the canonical description lives in the project's GitHub wiki "Key Uri Format" page, and the source repository was archived (made read-only) in April 2021.[1] The two underlying OTP algorithms predate the URI: HOTP (HMAC-based counter OTP) and TOTP (time-based OTP) are the IETF standards that the hotp and totp types implement.[1] The Key Uri Format document references RFC 3548 (Base32), RFC 3986 (URI/percent-encoding) and RFC 5234 (ABNF), and describes the HOTP/TOTP algorithm implementations rather than re-specifying them.[1] In 2024–2025 İlteriş Yağıztegin Eroğlu authored an IETF Internet-Draft (draft-linuxgemini-otpauth-uri) to formalise the schema for TOTP/HOTP token generators; it expired (last updated 17 February 2025) and is not endorsed by the IETF.[2]
Technical specification
The grammar is otpauth://TYPE/LABEL?PARAMETERS.[1]
- Scheme:
otpauth://.[1] - Type:
totporhotp.[1] - Label: identifies the account; format
issuer (":" / "%3A") *"%20" accountname, e.g.Example:alice@google.comorProvider1:Alice%20Smith. The issuer prefix is optional but recommended.[1]
Parameters:[1]
| Parameter | Required | Values / default | Notes |
|---|---|---|---|
secret |
Yes | Base32 key per RFC 3548 | RFC 3548 §2.2 padding "is not required and should be omitted" |
issuer |
Strongly recommended | URL-encoded string (RFC 3986) | Should match the label's issuer prefix when both are present |
algorithm |
No | SHA1 (default), SHA256, SHA512 |
Currently ignored by Google Authenticator |
digits |
No | 6 (default) or 8 |
Ignored on Android/BlackBerry implementations |
counter |
HOTP only | integer | Required for hotp; sets initial counter value |
period |
No | integer seconds, default 30 |
TOTP only; currently ignored by Google Authenticator |
Example TOTP URI:[1]
otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example
Comprehensive example:[1]
otpauth://totp/ACME%20Co:john.doe@email.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30
The whole string is embedded in a standard qr-code for enrolment scanning.
Use cases
- 2FA enrolment: a service displays a qr-code containing the otpauth URI; the user scans it with an authenticator app, which derives the rolling 6/8-digit codes thereafter.[1]
- Cross-vendor interoperability: because the format is shared, the same enrolment QR works across Google Authenticator and third-party apps; libraries such as PyOTP and the YubiKey OATH application parse the same
otpauth://string.[3][6]
Implementations
- PyOTP — Python; implements server-side HOTP and TOTP and the otpauth provisioning URI; ~3.3k stars, active 2026.[3]
- otpauth (hectorm) — JavaScript/TypeScript; OTP library with a dedicated
URIclass for parsing/serialisingotpauth://; ~1.5k stars, active 2026.[1][4] - speakeasy — Node.js HOTP/TOTP generator with Google Authenticator support; ~2.8k stars, last active 2023, marked not maintained.[5]
- YubiKey OATH (YubiKey SDK) — documents parsing the otpauth URI string to load OATH credentials onto hardware tokens.[6]
Comparison
- TOTP vs HOTP:
totpcodes roll on a time interval (period, default 30 s) and need no shared counter;hotpcodes advance on an event counter and therefore require thecounterparameter at provisioning so client and server start in sync.[1] - otpauth URI vs raw secret entry: the URI bundles secret, issuer, algorithm, digit count and period into one scannable string, removing the error-prone manual Base32 key entry; legacy apps that ignore
algorithm/digits/periodsimply fall back to the SHA1/6-digit/30-second defaults.[1]
Fun facts
- Google Authenticator famously ignores the
algorithm,digitsandperiodparameters, silently assuming SHA1 / 6 digits / 30 seconds — so a SHA256 or 8-digit enrolment can break on it even though the parameters are part of the format.[1] - The secret deliberately omits Base32 padding: RFC 3548 §2.2 padding "is not required and should be omitted" in otpauth URIs.[1]
Status
The otpauth URI is the de facto active standard for 2FA enrolment QR codes, anchored by the Google Authenticator Key Uri Format wiki and supported across the major authenticator apps and OTP libraries.[1][3] There is no ratified RFC; the closest formalisation effort, the linuxgemini IETF draft, has expired without IETF endorsement.[2]
Sources
1 Key Uri Format — google/google-authenticator Wiki — GitHub, 2021 2 draft-linuxgemini-otpauth-uri — Usage specification of the otpauth URI format — IETF Datatracker, 2025 3 PyOTP — Python One-Time Password Library — GitHub, 2026 4 otpauth (hectorm) — GitHub, 2026 5 speakeasy — GitHub, 2023 6 URI string format — YubiKey OATH — Yubico, 2025
Deployments
No country reports mention this standard by name.
Regions / aggregations not mapped to a single country
- Universal