A 2FA QR code is a QR code that contains an otpauth:// link, which authenticator apps read to enroll an account: the link holds the account label, the shared secret key, and settings such as the number of digits and the refresh period. This generator builds that link in your browser. The secret is not uploaded, but it is inside the finished image, so the image is as sensitive as a password.
When would you need this?
- Developers testing an enrollment flow for their own service.
- Administrators provisioning tokens where a secret already exists in a system they control.
- Individuals re-creating an enrollment code from a secret key they saved when they first set up an account.
If a website offers you a QR code to set up two-factor authentication, use that one. Do not invent your own secret for an account: the service must know the same secret to verify your codes.
How do you make a 2FA QR code?
- Pick Time-based (TOTP), the usual choice, or Counter-based (HOTP).
- Enter the Issuer / Service and the Account Name that the app should display.
- Paste the Secret Key in Base32. Spaces are removed and letters uppercased.
- Leave the advanced options at their defaults unless your system requires otherwise.
- Scan with the app and check that the account appears with the codes your server expects.
With the defaults (SHA1, 6 digits, 30 seconds) and the placeholder secret, the code holds:
otpauth://totp/ACME%20Corp%3Ajane%40example.com?secret=JBSWY3DPEHPK3PXP&issuer=ACME+Corp
Changing algorithm, digits, and period adds parameters to the link:
otpauth://totp/ACME%20Corp%3Ajane%40example.com?secret=JBSWY3DPEHPK3PXP&issuer=ACME+Corp&algorithm=SHA256&digits=8&period=60
Why should you leave the defaults alone?
Google's own Key URI Format page states that Google Authenticator ignores the algorithm and period parameters, and that on Android and BlackBerry it ignores digits. If you build a code with SHA256, 8 digits, or a 60-second period and someone scans it in an app that ignores those settings, the app will compute codes with SHA1, 6 digits, and 30 seconds. They will never match your server, and the user will think the code is broken.
Other authenticator apps may honor the extra parameters, but that is a per-app fact you need to test. The safe rule: use the defaults for any code that ordinary users will scan, and use custom values only in a controlled setup where you know the app.
What is inside the link?
| Part | Meaning |
|---|---|
totp or hotp | Time-based or counter-based codes. HOTP links also carry counter=0 |
Label (Issuer:account) | What the app shows in its list |
secret | The Base32 shared key. Google's format page says padding is not required and should be omitted |
issuer | The service name, repeated as a parameter so newer apps display it correctly |
How do you handle the secret safely?
- Treat the PNG or SVG like a password. Anyone with the image can generate your codes.
- Do not email it, paste it into chat, or leave it on a shared screen. Do not store it in a cloud photo library that syncs.
- Delete the image after enrollment, and keep the secret in a password manager if you need a backup.
- Use a computer you trust. The generator runs locally, but a compromised device can still read the screen.
For how these codes fit in a wider account-security picture, see Google 2FA QR codes, and for the risk of QR codes generally, can QR codes be hacked?
How do you test it?
Scan with the actual app your users will use, then compare the six-digit code against one your server computes for the same time. If they differ, the parameters or the secret are wrong. Check the export with the QR validator. For screenshots you must share, use a throwaway secret.