Build an OTPAuth URI — Free otpauth:// Link Generator
Fill in the account label, issuer, and secret fields and the OTPAuth URI Builder assembles a standards-compliant otpauth:// link for TOTP or HOTP two-factor setup — the exact link format that's normally hidden inside an enrollment QR code. Set the algorithm, digits, and period or counter to match what the receiving app expects, and copy the finished URI straight out of your browser.
When you're building two-factor authentication (2FA) into your application or onboarding users to a soft token app, the details inside a otpauth URI builder determine whether your token generator correctly produces a verification code — or fails silently with no useful error. Understanding every segment of the otpauth:// URI gives you precise control over how credentials are set up, displayed, and associated with user accounts across every major token app in the ecosystem.
What Is the otpauth:// URI Scheme and How Authenticators Parse It
The otpauth uri string format is a standardised key format used to transfer token setup data — including a shared key and related parameters — from a service into a token app or password manager. Originally formalised by Google and documented in the Google Authenticator key URI format page, the format is now registered with IANA as a provisional address scheme and forms the backbone of credential setup for mobile auth clients worldwide.
When your camera app scans a matrix code containing an otpauth:// link, the token app registered as a handler for the otpauth:// uri scheme parses each component — otp-type, label, and url query parameters — and stores the resulting account data locally. This producer consumer role demands strict processing rules to ensure consistent behavior across platforms including iCloud Keychain and similar apps.
URI Syntax Overview for TOTP and HOTP Types
The general uri string format follows a clear template:
otpauth://TYPE/LABEL?PARAMETERSUsing the grammar notation defined in the specification document (Augmented Backus-Naur Form), the full address syntax — expressed in augmented backus-naur form — is:
uri = "otpauth://" otp-type "/" label "?" parameter *( "&" parameter )
otp-type = "totp" / "hotp"
label = issuer-label ( ":" / "%3A" ) *"%20" account
/ issuer-label
/ account
issuer-label = 1*( unreserved / pct-encoded / sub-delims / "@" )
account = 1*( unreserved / pct-encoded / sub-delims / "@" )
parameter = secret / algorithm / digits / counter / period / issuer / extension
secret = "secret=" 1*( %x41-5A / %x32-37 ) ; Base32 A-Z2-7
algorithm = "algorithm=" ( "SHA1" / "SHA256" / "SHA512" )
digits = "digits=" ( "6" / "8" )
counter = "counter=" 1*DIGIT
period = "period=" 1*DIGIT
issuer = "issuer=" *pchar
extension = 1*( ALPHA / DIGIT / "-" / "_" ) "=" *pcharPer the grammar syntax rules, all quoted literals are treated without case sensitivity. Producers of an address string SHOULD emit lowercase forms — otpauth, totp, hotp — for consistency. Parameter values that contain a literal ampersand MUST percent-encode it as %26, following address-format rules from the URI generic syntax document.
Supported OTP Types: TOTP vs HOTP Distinguished
The otp-type segment distinguishes between two token-generation algorithm families supported across the oath credentials norm:
- totp — Time-Based One-Time Password, defined in the relevant IETF document. A time-based scheme generates a fresh 2FA code every 30 second window (the default) by applying a time-based algorithm over the current Unix timestamp and the key. This is the type used by the vast majority of soft tokens and token apps today.
- hotp — HMAC-Based One-Time Password, defined in the counter-based token specification. Counter-based mode uses a monotonically incrementing counter as its moving factor, applying the counter algorithm — specifically an HMAC-SHA-1 hashing function — to produce each code. This is the approach used by hardware tokens and the original S/KEY system.
Understanding the difference between time-based and counter-based schemes determines which parameters are mandatory versus not in your URI.
Full otpauth URI Builder: Format and Structural Segments
Every component of the address layout carries a specific role. A URI producer assembles these segments; a URI consumer decodes them using address-decoding rules from the URI generic syntax document to reconstruct the token setup object.
OTP Type Segment and Case Handling
The otp-type value is placed immediately after otpauth:// and before the first forward slash. Valid values are totp and hotp only. The matching is without case sensitivity by the grammar syntax, but lowercase is the preferred form for URI producers aiming at backward compatibility with existing deployments.
Label Segment: Account Identifier and Issuer Label Prefix
The label identifies the account being set up and doubles as the unique account identifier within a token app. Its address layout supports two structures and contains specific label components:
- With issuer prefix:
issuer-label:account— the prefix is separated from the account name by a literal colon or the address-encoded colon%3A. Spaces between the label separator and the account name are encoded as%20. - Without issuer prefix:
accountonly — the entire label is treated as the account name.
Label parsing by a URI consumer follows this order: locate the separator colon (literal : or percent-encoded %3A), split at the first occurrence, then percent-decode each label component. If either decoded issuer-label or decoded account contains a colon, the consumer MUST reject the URI. This label collision prevention rule is essential for account matching integrity.
The account name is typically the user's email address. For example, [email protected] is a valid account value. When both a prefix and an account are present, the resulting label prevents collisions between different user records that share the same account name across different providers — a critical function of issuer handling in multi-account scenarios.
URI Parameters Reference for the otpauth URI Builder
Query parameters are appended after the ? in the address query component. Parameter order is not significant. Each known parameter MUST appear at most once; a consumer MUST reject the URI if any known parameter appears more than once. The following reference table covers all parameters, including their mandatory or supplementary status, valid values, applicable token type, and description.
| Name | Required / Optional | Valid Values | Applicable Type | Description |
|---|---|---|---|---|
secret | Mandatory | Unpadded Base32 (A–Z, 2–7) | Both | The shared key serialised using the base32 alphabet from the data-encodings document. Padding omitted; producers SHOULD emit uppercase, consumers MAY accept lowercase for cross-app support. |
issuer | Strongly recommended | Any pchar string (domain name recommended) | Both | Identifies the service provider. Used as the primary identifier for account matching and credential suggestion. A stable identifier such as a domain name is preferred. |
algorithm | Supplementary | SHA1 (default), SHA256, SHA512 | Both | The hashing function used by the token algorithm. Default is SHA1. Consumers MUST support SHA1; SHOULD support SHA256 and SHA512. |
digits | Supplementary | 6 (default), 8 | Both | Number of digits in the one-time code. Default is 6 digits. Consumers MUST support 6; SHOULD support 8 digits. |
period | Supplementary (TOTP only) | Positive integer seconds (default 30) | TOTP only | Defines the validity window in seconds for a time-based code. Common values: 15 seconds, 30 seconds (default), 60 seconds. MUST be ignored for HOTP. |
counter | Mandatory (HOTP only) | Non-negative integer | HOTP only | Sets the starting counter value for setting up counter-based tokens. MUST be ignored for TOTP. |
Secret Parameter: Base32 Encoding Rules
The secret carries the raw shared key used for every token-generation computation. Its value MUST use unpadded base32 with the alphabet A–Z and 2–7 as specified in the data-encodings document. Note that padding omitted means the trailing = characters normally present in standard serialisation are dropped. Producers SHOULD emit uppercase base32 text. Consumers MAY accept lowercase for cross-app support with existing deployments.
The base32 helper utilities in many open source libraries (such as the helper in Yubico.Core) handle serialisation and deserialisation automatically. Do not confuse base32 with hex-based base16 or binary-to-text base64 — only the base32 alphabet is valid for the secret value. The key material is sensitive; treat it as confidential at all times.
Issuer Parameter: Account Association and Stable Identifier
The issuer field is strongly recommended for every URI you produce. It serves as a service identifier that tells the token app which relying party issued the token, enabling reliable account association in a password manager or token app that manages multiple accounts. A domain name controlled by the service (for example, example.com) makes the most stable identifier for long-term account matching and credential suggestion across app upgrades.
The issuer field is address-encoded according to the URI generic syntax document. When both an issuer label prefix in the label and an issuer field are present, the consumer SHOULD treat the issuer field as authoritative for account matching and MAY use the prefix for display. The two values SHOULD match in most setups for backward compatibility, but a consumer MUST NOT reject the URI solely because they differ.
Algorithm, Digits, and Period Parameters: Platform Caveats
- algorithm
- The algorithm parameter selects the cryptography function applied during code generation. Valid values are
SHA1,SHA256, andSHA512. The default is SHA1, which aligns with the HMAC-SHA-1 hashing approach used by the counter-based token document and is the safest choice for maximum cross-app support. Reminder: Currently, the algorithm parameter is ignored by the authenticator app on Android and Blackberry. If your token clients include that app, set algorithm to SHA1 or omit it entirely. - digits
- Controls the number of digits in the output code. The digits parameter accepts
6or8. The default is 6 digits. Yubico's reference guide also notes7as a valid value in some implementations, though the IETF draft restricts valid values to 6 and 8. Reminder: Currently, on Android and Blackberry the digits parameter is ignored by the authenticator app. Avoid relying on 8-digit codes when that app is your target token client. - period
- The time-window parameter defines the validity window in seconds over which a time-based code remains valid. Default is 30 seconds. Supported values include 15 seconds, 30 seconds, and 60 seconds. This parameter applies to time-based tokens only and MUST be ignored for counter-based tokens. Reminder: Currently, the time-window parameter is ignored by some authenticator app implementations. If you need a non-default validity window, verify your target token app supports it before deploying.
Counter Parameter for HOTP Provisioning
The counter parameter is mandatory for counter-based tokens and sets the starting counter value from which the counter increments. The starting counter value is typically 0 for new setups, but may be set higher if the token is being migrated. The counter must be a non-negative integer. Setting up counter-based tokens without a counter causes the consumer to reject the URI as malformed.
otpauth URI Builder: Constructor and Static Methods
The interactive tool above lets you fill in each parameter through a live form interface, automatically producing a correctly address-encoded output and a scannable matrix code. Under the hood, libraries implementing the scheme expose a programmatic API with a constructor and two static methods for parse and stringify operations.
Constructor and Builder Settings
When working with the library programmatically, you instantiate a new URI object using the constructor pattern. The new URI() constructor accepts an optional config object that sets the token type, label, issuer, secret, algorithm, digits, and period (for time-based) or counter (for counter-based):
// Construct a TOTP URI object
const totpUri = new OTPAuth.URI({
type: 'totp',
label: '[email protected]',
issuer: 'Example',
secret: OTPAuth.Secret.fromBase32('JBSWY3DPEHPK3PXP'),
algorithm: 'SHA1',
digits: 6,
period: 30
});
// Construct an HOTP URI object
const hotpUri = new OTPAuth.URI({
type: 'hotp',
label: '[email protected]',
issuer: 'Example',
secret: OTPAuth.Secret.fromBase32('JBSWY3DPEHPK3PXP'),
algorithm: 'SHA1',
digits: 6,
counter: 0
});The constructor returns a URI object (a time-based or counter-based instance depending on type) that can be passed directly to the static stringify method.
Static Parse and Stringify Utilities
Two static methods — static parse and static stringify — handle conversion between address strings and token objects:
OTPAuth.URI.parse(uri: string, config?: { hmac?: (algorithm: string, key: Uint8Array, message: Uint8Array) => Uint8Array }): HOTP | TOTP- Parses a key URI string and returns an HOTP or TOTP object. The supplementary config accepts a custom HMAC function taking a
keybyte array and amessagebyte array — useful when you need to substitute the default HMAC implementation. The parse method validates all parameters and will throw if the raw address is malformed. OTPAuth.URI.stringify(otp: HOTP | TOTP): string- Encodes an HOTP or TOTP object into a key URI string. The static stringify method returns a fully address-encoded output ready for embedding in a matrix code or transmitting over a secure channel. The result conforms to the key format documented in the reference page.
Extension parameters and supplementary settings
Producers MAY include extension parameters beyond the norm. A URI consumer receiving unrecognised parameters SHOULD ignore them unless local policy requires otherwise. This forward-compatibility rule supports the consistent behavior needed as the token ecosystem evolves. When using the supplementary settings parameter in the parse method, your custom cryptography function receives the algorithm name as a string alongside the key byte array and message byte array, giving you full control over code generation using industry-standard identity verification cryptography.
Worked URI Examples: TOTP, TOTP with Issuer, and HOTP
The following three examples demonstrate the full range of valid constructions using the otpauth:// URI scheme, from the minimal mandatory case through to a fully specified counter-based URI. Each example is annotated to explain every component.
Basic TOTP URI — Minimal Valid Token URI
This minimal URI includes only the mandatory secret value and a simple account label with no issuer prefix. It represents the smallest valid time-based URI a producer can emit:
otpauth://totp/[email protected]?secret=JBSWY3DPEHPK3PXPotpauth://— the scheme identifiertotp— the token-type, selecting the time-based algorithm[email protected]— the label (account name only; no prefix)secret=JBSWY3DPEHPK3PXP— the key value; an uppercase unpadded base32 serialised shared key
All other parameters (issuer, algorithm, digits, period) fall back to their defaults: SHA1, 6 digits, and a 30-second window. While valid, this form is not recommended for production because the absence of an issuer makes account association ambiguous when users hold multiple tokens.
TOTP URI with Issuer and Percent-Encoded Label Prefix
This form is the recommended pattern for multi-account disambiguation. The issuer appears in both the label prefix and the issuer query parameter. Spaces in the issuer string are address-encoded as %20:
otpauth://totp/Big%20Corporation:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=Big%20CorporationBig%20Corporation— the issuer-label prefix (address-encoded, spaces as%20):— the label separator colon between prefix and account[email protected]— the account identifier (email address)issuer=Big%20Corporation— the issuer field; the address-encoded value that the consumer uses for account matching
When scanning matrix codes containing this URI, the token app displays "Big Corporation" as the service name. The issuer field enables import into password managers that support identifier lookups by domain or service name. Note that the issuer label prefix and issuer field carry the same value here — consistent with behavior in deployed systems and the key format reference page.
HOTP URI with Counter and All Optional Parameters
This fully specified counter-based URI demonstrates setup with every supplementary parameter explicitly set, giving the consumer a complete token configuration:
otpauth://hotp/Example:alice?secret=JBSWY3DPEHPK3PXP&issuer=Example&algorithm=SHA1&digits=6&counter=0hotp— selects the HMAC-based counter algorithm familyExample:alice— label with issuer prefixExampleand accountalicesecret=JBSWY3DPEHPK3PXP— base32 serialised shared key (uses the base32 alphabet)issuer=Example— the issuer field matching the label prefix for service associationalgorithm=SHA1— the hashing function; SHA1 is mandated by the counter-based token document and aligns with the counter algorithm definitiondigits=6— explicitly sets 6-digit outputcounter=0— the starting counter value; this counter begins at zero
The counter-based object produced by parsing this URI will generate codes by computing HMAC over the counter value and the shared key. Each time a code is used, the counter on both client and server increments, maintaining synchronisation without needing a clock.
Security Considerations and Data Protection for otpauth URI Scheme Handling
The address format does not inherently introduce vulnerabilities, but the secret value it carries is a bearer credential — possession of the URI is equivalent to possessing the second factor. Careful handling is essential to avoid account compromise.
- Treat URIs as sensitive secrets. An
otpauth://URI encodes the entire shared key in plaintext within the query string. Anyone who obtains your URI can generate valid codes and bypass the second factor on the associated account. - Use encrypted channels exclusively. Deliver setup data only over secure channels (HTTPS). Avoid transmitting links or scanning matrix codes over insecure communication channels — even a brief interception exposes the key material.
- Avoid logging URIs. Applications SHOULD implement log avoidance for raw address values. Do not write full URIs to logs, analytics pipelines, or crash reports. Once logged, setup data may persist indefinitely in your infrastructure.
- Data protection of label and issuer fields. The label and issuer fields reveal account identifiers and service associations. Applications SHOULD minimise retention of these values and SHOULD NOT share raw address values across process boundaries unless required for explicit user action. These data-protection concerns are especially important in multi-tenant environments.
- Phishing detection. Consumers SHOULD display issuer and account information clearly before completing token import, enabling users to detect phishing attempts or setup mistakes. Digital signatures on setup payloads provide an additional safeguard where supported.
- IANA registration status. The
otpauth://scheme is currently registered as a provisional address scheme in the IANA URI Schemes registry. The IETF internet-draft (draft-andesco-otpauth-uri-00, published by the Network Working Group in February 2026) proposes updating this to a full registration. Handler registration for the scheme in mobile operating systems enables the camera app to route scanned matrix codes directly to your token app. - Parameter support gaps. Be aware that the algorithm parameter, digits parameter, and time-window parameter are all ignored by some token apps on Android. Design your token method around SHA1, 6-digit codes, and a 30-second window unless you have confirmed support in your target token clients.
Security note: The shared key in your URI is the cryptographic root of your multi-factor identity verification credential. Treat it with the same care as a private key — generate it from a cryptographically secure random source, store it encrypted, and revoke it immediately if you suspect exposure.
References and Acknowledgments for otpauth Specification
The address format draws on a rich set of normative and informative norms. Understanding these references helps you interpret processing rules and ensure your implementation maintains cross-app support with the broader token ecosystem.
Normative References
- RFC 4226 — HOTP: An HMAC-Based One-Time Password Algorithm
- Defines the HMAC-based counter token algorithm. Specifies the use of HMAC-SHA-1, the counter-based moving factor, and the truncation function that produces passcodes. This is the foundational document for the
hotptoken type and the counter algorithm used in counter-based URIs. - RFC 6238 — TOTP: Time-Based One-Time Password Algorithm
- Extends the counter-based document to define the time-based token algorithm. Specifies the 30-second window default, the Unix time moving factor, and the use of SHA1, SHA256, or SHA512 as the hashing function. This document governs the
totptoken type and the time-based algorithm used in time-based URIs. - RFC 3986 — Uniform Resource Identifier (URI): Generic Syntax
- Defines address generic syntax, address serialisation, address deserialisation, percent-encode rules, and the address query component (query string). All percent-encoded and percent-decoded operations in the scheme follow address-decoding rules from this document.
- RFC 4648 — The Base16, Base32, and Base64 Data Encodings
- Specifies the base32 serialisation used for the secret value, including the alphabet (A–Z, 2–7) and the rule that padding omitted is acceptable for this application.
- RFC 5234 — Augmented BNF for Syntax Specifications: ABNF
- Defines the Augmented Backus-Naur Form (ABNF) notation used to express the address syntax definition throughout the scheme specification. The grammar rules in this document govern case-insensitive matching and syntax rules for all address production components.
Informative References
- Google Authenticator Key URI Format — The reference page documents the key format conventions that originally formalised the scheme. This is the primary informative reference for current token ecosystem behavior and the key format conventions.
- Apple iCloud Keychain Verification Codes — Apple's reference guide on securing logins describes code setup, token import, and mobile auth behavior on iOS. Apple's guidance is largely aligned with the key format reference.
- RFC 3548 — The Base16, Base32, and Base64 Data Encodings (predecessor) — Referenced in some earlier reference material (including Yubico's) for base32 serialisation of the secret value. RFC 4648 supersedes this document but both specify the same alphabet used in secret serialisation.
- RFC 2289 / S/KEY — The S/KEY system (originally from Bell Labs and Bellcore, later formalised as RFC-2289) provides the historical context for single-use codes and the one-way function approach to account security. The unix skey command and MS-DOS client implementations from SRI International represent early deployed systems in the history of token generation. The Lamport method and Lamport signatures (published in Communications of the ACM) form the theoretical foundation underlying all modern single-use token systems.
Acknowledgment is due to the maintainers and implementers across the open source token ecosystem — including the teams at Apple and Google — whose reference material and deployed systems shaped the cross-app behavior that this protocol codifies. The IETF Network Working Group internet-draft (draft-andesco-otpauth-uri-00) by Andrew Escobar represents the most current effort to formalise these conventions into a normative norm with full IANA registration.
Frequently Asked Questions
- What is an otpauth:// URI?
- It's the de facto standard URI scheme authenticator apps use for enrollment -- otpauth://TYPE/LABEL?secret=...&issuer=...&algorithm=...&digits=...&period=.... It was never a formal RFC, but Google Authenticator's original implementation became the shared convention every major app (Authy, Microsoft Authenticator, 1Password, Bitwarden) now supports.
- What's the difference between TOTP and HOTP?
- TOTP (time-based) generates a new code every fixed period (usually 30 seconds) based on the current time. HOTP (counter-based, the older of the two, defined in RFC 4226) generates a new code each time it's used, based on an incrementing counter both sides track. Almost all modern 2FA setups use TOTP; HOTP mainly appears in older hardware tokens.
- Why does the label include the issuer?
- Authenticator apps display the label to help users tell accounts apart. Prefixing it with 'Issuer:' (e.g. 'GitHub:[email protected]') lets the app group and label entries by service even if you have multiple accounts with the same username across different sites -- this tool does that automatically when you fill in the Issuer field.
- Do I need to change the algorithm, digits, or period?
- No -- leave them at the defaults (SHA1, 6 digits, 30-second period) unless a specific service's documentation tells you otherwise. Those are the universal defaults every authenticator app assumes when a URI omits them, which is why this tool only adds them to the output when you've changed them from default.
- Does this tool store or transmit my secret?
- No. The URI is built entirely in your browser from the values you type. Nothing is sent to a server, logged, or stored -- reload the page and everything is gone.