otpauth:// URI parser

Paste the otpauth:// link behind a 2FA QR code and read every field it carries — type, issuer, account, base32 secret, algorithm, digits, and period or counter — with spec defaults filled in and compatibility warnings flagged. Runs in your browser; the secret never leaves your device.

Try:
Parsed fields

About this tool

A two-factor setup QR code is just a picture of a text link. Decode the QR and you get an otpauth:// provisioning URI — the Key Uri Format that Google Authenticator, Authy, 1Password, Microsoft Authenticator and effectively every other authenticator app reads. This tool takes that link apart and shows you every field it carries: the OTP type, the issuer, the account name, the base32 shared secret, the HMAC algorithm, the code length, and the time step (TOTP) or starting counter (HOTP).

It is a reader, not a code generator: it never contacts a server, and the secret you paste stays in your browser.

What you get back

Worked example

Input:

otpauth://totp/ACME%20Co:[email protected]?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30

Output with Readable lines selected:

type:        totp
issuer:      ACME Co
account:     [email protected]
label:       ACME Co:[email protected]
secret:      HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ
secret size: 32 chars, 20 bytes
algorithm:   SHA1
digits:      6
period:      30 seconds

Pick JSON instead for a machine-readable object (including defaults_applied and warnings), or ASCII table for something you can paste into a terminal or a wiki.

Output formats and options

Limits and edge cases

FAQ

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

The parsing runs entirely in your browser via WebAssembly — nothing is uploaded, and there is no server to log it. That said, a secret is a live credential: if you only need to show someone the shape of a URI, tick Mask the secret so the output carries ******** plus the true secret_chars / secret_bytes instead of the real value.

My URI has no algorithm, digits, or period. Is it broken?

No — those parameters are optional. The Key Uri Format says a reader must assume SHA1, 6 digits, and a 30-second period when they are absent, which is exactly what this tool does. Every value that came from a default rather than from your URI is listed under defaults_applied, so you can tell the two apart at a glance.

Why does it warn about the issuer when the URI clearly has one?

The issuer can appear in two places: as the label prefix before the colon, and as the issuer= query parameter. The spec wants both, and wants them identical. If only one is present you get a compatibility warning, because some apps read the other one. If they disagree (GitHub:alice with issuer=GitLab) the mismatch is flagged too — the issuer= parameter is what this tool reports as the effective issuer, but apps genuinely differ on which one they display.

Why is my secret rejected as "not base32"?

Base32 (RFC 4648) uses only AZ and the digits 27. The characters 0, 1, 8 and 9 are not in the alphabet, so a "secret" containing them is either hex, base64, or a typo — an authenticator app would generate wrong codes from it. Spaces, hyphens, underscores, = padding and lower case are all fine: they are normalized away first, and you get a warning saying the secret was cleaned up. A length that can't come from whole bytes (like 3 characters) is rejected for the same reason.

What's the difference between the period and the counter?

period belongs to TOTP: it is the number of seconds each code is valid for, normally 30. counter belongs to HOTP: it is the starting value of a counter that advances every time a code is used. A URI should carry exactly one of them. An HOTP URI without a counter is an error; a counter= on a TOTP URI (or a period= on an HOTP one) is reported as an ignored parameter rather than a failure, because that is how apps treat it.

Can it decode the QR image itself, or a migration export?

Not here — this tool starts from the URI text. Scan or decode the QR code first with a QR reader, then paste the otpauth://… string it produces. Multi-account otpauth-migration:// exports are a different, protobuf-encoded format and need to be expanded into individual otpauth:// URIs before this parser can read them.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool otpauth-uri-parser "otpauth://totp/ACME%20Co:[email protected]?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30"

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/otpauth-uri-parser/?uri=otpauth%3A%2F%2Ftotp%2FACME%2520Co%3Ajohn.doe%40email.com%3Fsecret%3DHXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ%26issuer%3DACME%2520Co%26algorithm%3DSHA1%26digits%3D6%26period%3D30&format=json&mask_secret=true&strict=true

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.