Encoding / Decoding

Base32 Encode / Decode

Convert UTF-8 text to and from RFC 4648 Base32.

RFC 4648 Base32
UTF-8 text, processed locally
Result
The result will appear here.

Base32 Encode / Decode

Convert UTF-8 text to RFC 4648 Base32 or decode it back to text. Whitespace, hyphens, and trailing = padding are accepted while decoding.

Boundaries

  • Useful for printable identifiers and common TOTP secret representations
  • Base32 is encoding, not encryption, and does not protect sensitive data

Base32 turns UTF-8 text into the 32-symbol alphabet of RFC 4648 — A–Z plus 2–7 — and turns it back. Every symbol is a capital letter or a digit, so the output survives case folding, handwriting, DNS names and TOTP secret fields, at the cost of about 60% size growth.

Five bits per symbol, eight symbols per five bytes

The encoder reads the input as UTF-8 bytes and emits one symbol per 5 bits, so a full quantum is 5 bytes to 8 symbols, not Base64 style 3 bytes to 4. The alphabet is fixed: A–Z mean 0–25, 2–7 mean 26–31, and the digits 0, 1, 8, 9 are left out so nothing can be misread as O, I or B. Eight symbols carry exactly 40 bits of data, which makes the output 1.6 times the byte length before padding: a 12-byte string becomes 20 symbols. Trailing bytes are not dropped. A leftover of 1, 2, 3 or 4 bytes produces 2, 4, 5 or 7 symbols, with zero bits shifted in to fill the last 5-bit group.

Which = counts are legal, and what the last symbol may hold

Padding is arithmetic, not decoration. One leftover byte gives 2 symbols plus 6 equal signs, 2 bytes give 4 plus 4, 3 bytes give 5 plus 3, 4 bytes give 7 plus 1. A symbol count of 1, 3 or 6 modulo 8 can never represent whole bytes, so this decoder rejects those lengths, and a partial group such as MZXW6= is refused while the same five symbols without padding decode to foo. The final symbol must also leave its unused low bits at zero: for a 1-byte payload the second symbol index has to be a multiple of 4, so a encodes as ME, and MZ fails the non-zero trailing bits check instead of returning a byte.

Base32hex and Crockford are different alphabets

RFC 4648 also defines Base32hex, which runs 0–9 then A–V and keeps sort order identical to byte order; DNSSEC NSEC3 owner names use it. Crockford Base32 drops I, L, O and U from A–Z to survive sloppy reading, and z-base-32 reorders letters for shorter human strings. This tool implements only the standard A–Z plus 2–7 set. Feed it a Base32hex payload and two things can happen: characters 0, 1, 8, 9 are rejected by the character check, but a payload made only of A–V decodes silently into the wrong bytes, because A is 0 here and 10 there.

Worked example

Encoding mixed ASCII and CJK text

Input
hello 世界
Output
NBSWY3DPEDSLRFXHSWGA====

The input is 12 UTF-8 bytes: 5 ASCII letters, 1 space, and two 3-byte characters. The first 10 bytes form two 5-byte quanta and yield 16 symbols, the remaining 2 bytes yield 4 more, so there are 20 symbols padded with four = to reach 24. Ticking omit padding gives NBSWY3DPEDSLRFXHSWGA, which still decodes because padding is optional on input.

Limits and pitfalls

  • Output is 60% larger than the input before padding (8 symbols per 5 bytes); for a 1 KB blob that is 1600 characters, so switch to Base64 when size matters and case does not.
  • Decoding is UTF-8 only: the result is produced with a fatal TextDecoder, so a Base32 payload of compressed data, image bytes or raw key material errors out instead of yielding bytes.
  • Missing padding is tolerated, wrong padding is not: MZXW6 decodes but MZXW6= is refused because the symbol count is not a multiple of 8.
  • Whitespace and hyphens are stripped silently to support grouped secrets, so a hyphen placed in the wrong position changes the decoded bytes rather than raising an error.
  • Only the RFC 4648 alphabet is accepted; Base32hex, Crockford and z-base-32 payloads decode to wrong bytes or fail the character check, and lowercase input is folded to uppercase before lookup.

Related tools

When it goes wrong

I added a couple more = signs and the error now blames my characters, not the padding.

CauseThe character check runs first and its pattern allows at most six trailing =. With seven or more the value never reaches the padding test, so the alphabet message appears even though every symbol is legal.

FixCut back to six or fewer and read the error again. This page's own sample IRSXMZLMN5YGK4RAKRXW63DCN54A is 28 symbols, so it takes exactly 4 — anything past that is the wrong correction.

The value arrived without padding, I padded it until the total looked like a multiple of 8, and it still says the padding is invalid.

CauseTwo conditions, not one: the total length must be a multiple of 8, and the count of = must equal (8 - symbols % 8) % 8. A guess that satisfies only the first fails the second — 28 symbols want 4, 26 want 6, 20 want 4 again.

FixDelete every = first: this decoder accepts unpadded values, so the shortest form is always safe here. Add padding back only for a consumer that rejects unpadded input.

A 32-character secret from my authenticator setup decodes to an error about invalid UTF-8 instead of giving me the key.

CauseThose 20 bytes are random binary, and the decode ends with new TextDecoder("utf-8", { fatal: true }). A single byte such as 0x9f in the first group is enough to throw the whole result away.

FixTreat the secret as a string — it already is the key, and decoding it to text was never the goal. For the raw bytes use base64.b32decode in Python or the Hex tool instead of this pane.

I swapped one letter in the middle of a secret and it decoded without a word of complaint, into a different key.

CauseDecoding checks three things only: the character set, the length modulo 8, and that the unused low bits of the final symbol are zero. A substitution in the middle of the string lands on a whole 5-bit group and passes all three, because there is no checksum in RFC 4648.

FixCompare against the original value rather than trusting the absence of an error. If the 20 bytes still exist somewhere, re-encode those and diff the two strings; a silent pass proves nothing about correctness.

The result pane stays blank with no error, and I cannot tell whether the conversion even ran.

CauseAn empty or whitespace-only value compacts to an empty string and decode returns early with nothing, so no error is raised. The other cause is the mode toggle: a Base32 string pasted while Encode is selected comes back as Base32 of that string, which looks just as plausible.

FixCheck the segmented control above the textarea first, then clear and paste again in Decode mode. Re-encoding that 28-symbol sample returns 48 characters, so a result noticeably longer than the paste is the quickest proof the wrong mode was selected.

Base32 on this page, Base64 next door, or one line of Python

What you are doingBase32 on this pageWhat to reach for instead
A shared secret has to go into an authenticator appA TOTP secret is 20 random bytes, and 160 bits divide evenly by 5, so the canonical form is 32 symbols with no = at all. Paste it here and the character check fires on the first symbol outside A–Z and 2–7, which is the fastest way to catch a secret copied out of the wrong export.When the secret has to be generated rather than inspected, python3 -c "import os,base64;print(base64.b32encode(os.urandom(20)).decode())" prints exactly the 32-character shape this page accepts. Copy that output instead of a key that was retyped.
The encoded value is going into JSON or a config fileSize is the whole tax: 8 symbols per 5 bytes is 1.6 times the byte count, so 17 characters of text — Developer Toolbox — leave as 32 characters with four = appended.The Base64 tool on this site, at 4 characters per 3 bytes, roughly 1.34 times. Pay the extra 60% only when the transport folds case or a person has to read the string out loud; for a machine-to-machine field it buys nothing.
Someone has to copy the value off a screen onto paperThe result comes back as one unbroken run with no line breaks, so a slip costs the reader the whole string. The alphabet itself is kind, though: 0, 1, 8 and 9 are left out entirely, so O and 0 can never be confused.Group the output yourself — a hyphen every 4 symbols — and hand over the grouped form. The decoder here deletes spaces and hyphens before lookup, so the separators cost nothing and the paste still resolves to the same bytes.
The same conversion, a few hundred times, in a build stepOne paste, one conversion, no file picker and no batch entry. That is the right trade for a single secret and the wrong one for a column of them, where the manual step is what introduces the typo.Script it: base64.b32encode(b"Developer Toolbox") returns IRSXMZLMN5YGK4RAKRXW63DCN54A====, byte for byte what the Example button yields here. Node has no base32 encoding in Buffer — hex, base64, base64url, latin1, utf16le and utf8 only — so reach for Python or a library.
The payload is a gzip file or an image, not textDecode mode ends in a fatal UTF-8 TextDecoder, so the first invalid byte aborts the conversion and the pane shows an error instead of bytes. That check is deliberate; there is no byte view to switch to.Decode in a script straight to a file and confirm the header in the Hex tool — 1f 8b means gzip, 89 50 4e 47 means PNG. A text pane can never carry those bytes, so decide on the tool before pasting.

Frequently Asked Questions

Base32 or Base64 — which one should I use?
Prefer Base64: it is denser (about one-third overhead versus 60% for Base32). Two cases require Base32: TOTP two-factor secrets, which authenticator apps only accept as Base32, and human transcription scenarios, because Base32 uses only A–Z and 2–7, dropping the confusable 0, 1, 8, and 9.
Why do I get a length or padding error when decoding?
Base32 output length must be a multiple of 8, padded with = signs. The usual culprits are a dropped trailing = during transcription, or stray spaces and hyphens. This tool ignores whitespace and hyphens and repairs missing padding automatically.
Is it safe to convert my 2FA secret with this tool?
The conversion runs locally in your browser and is never uploaded. Still, a TOTP secret is equivalent to a password: clear it when you are done. Use this tool to debug and understand key formats; manage real secrets with a password manager.

Content reviewed: