How to convert Base32 to Base64
- Paste the Base32 into Input · Base32 (RFC 4648). Spaces between groups, lower case and missing
=are all fine. - Read the Base64 in Output · Base64. Untick Padding (=) under the output if the target does not want
=, or set Line wrap for long values. - Copy output. Base64 → Base32 (RFC 4648) in the direction toggle goes back, as does Base64 to Base32.
Examples
| Base32 | Base64 | Note |
|---|---|---|
JBSWY3DPEHPK3PXP | SGVsbG8h3q2+7w== | The example key from the Google Authenticator key URI docs, 10 bytes |
jbsw y3dp ehpk 3pxp | SGVsbG8h3q2+7w== | Same key, the grouped way apps display it |
GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ | MTIzNDU2Nzg5MDEyMzQ1Njc4OTA= | The RFC 6238 test secret, 20 ASCII digits |
RBGA56K5GUXFZY3PQMYQKS3ACLQI2W6K | iEwO+V01Llzjb4MxBUtgEuCNW8o= | 20 random-looking bytes |
MZXW6YQ | Zm9vYg== | Unpadded input; the padded form is MZXW6YQ= |
The first key decodes to the bytes 48 65 6c 6c 6f 21 de ad be ef: the word Hello! followed by de ad be ef. That is why its Base64 starts with SGVsbG8h, the Base64 of Hello!.
Why convert a 2FA secret to Base64
The Base32 form exists for people: it goes into QR codes and setup screens and can be typed on a phone. Code and configuration usually want the raw key, and Base64 is the common way to store raw bytes in JSON, YAML, environment variables and databases. Typical cases:
- Moving TOTP accounts from an exported list of
otpauth://links into a system that stores secrets as Base64. - Passing the key to an HMAC function or library that takes Base64 or bytes, for example when you verify codes on your own server.
- Comparing two copies of a secret. Different groupings, case or padding of the same Base32 all give one Base64 string, so equal output means equal keys.
A secret in Base64 is exactly as sensitive as the Base32 one, so store it where you would store a password.
Base32 to Base64 in Python
Python’s b32decode is strict about case and padding, so normalize the string first:
import base64
def b32_to_b64(secret):
s = secret.replace(" ", "").upper()
s += "=" * (-len(s) % 8)
return base64.b64encode(base64.b32decode(s)).decode()
b32_to_b64("jbsw y3dp ehpk 3pxp") # 'SGVsbG8h3q2+7w=='
Without the .upper() call, Python raises binascii.Error: Non-base32 digit found; without the padding line, Incorrect padding. See Base64 in Python for the Base64 side.
Common problems
- Error at a
9,8,1or0. These digits are not in RFC 4648 Base32. The value is probably base32hex or Crockford;91IMOR3F, for example, fails at position 1 here. Decode it on the Base32 decoder with the right From alphabet. - Error at a
-. Some sites show keys split with hyphens. Remove them; only whitespace is skipped. - The Base64 is correct but the server rejects codes. Check the other parameters: algorithm, digits and period must match on both sides, and the server clock must be close to the phone’s.
FAQ
How do I convert a Google Authenticator key to Base64?
Take the key from the secret= parameter of the otpauth:// link (or the text key shown under the QR code) and paste it here. JBSWY3DPEHPK3PXP becomes SGVsbG8h3q2+7w==.
Why is the Base64 shorter than the Base32?
Base64 stores 6 bits per character and Base32 stores 5, so the same bytes need fewer Base64 characters: 20 bytes are 32 Base32 characters but 28 Base64 characters.
Can I convert base32hex or Crockford Base32 here?
This page reads RFC 4648 Base32 only. Open the Base32 decoder, set From to Base32hex or Crockford Base32 and To to Base64.
How do I convert Base32 to Base64 on the command line?
With GNU coreutils: printf 'JBSWY3DPEHPK3PXP' | base32 -d | base64. The input must be upper case without spaces; tr -d ' ' | tr a-z A-Z cleans it up first.