Base32 encoder / decoder

Encode and decode Base32 (RFC 4648 §6) using the A-Z 2-7 alphabet.

Docify's Base32 encoder implements RFC 4648 §6 using the A-Z and 2-7 alphabet (32 characters) with = padding. Example: foobar encodes to MZXW6YTBOI======. Decoding is case-insensitive and accepts optional padding. This is not Crockford Base32 (used in ULIDs) or Base32hex — see our Base32hex tool for the 0-9 A-V alphabet. Nothing is uploaded.

Plain text
Base32 output

How it works

  1. Encoding: Input text is converted to UTF-8 bytes. Each group of 5 bytes (40 bits) becomes 8 Base32 characters. The last group is padded with = to make a multiple of 8 characters.
  2. Decoding: Base32 characters are converted back to bytes. The decoder is case-insensitive and strips whitespace. Padding is optional.
  3. Alphabet: A-Z (values 0-25) and 2-7 (values 26-31). Characters 0, 1, 8, 9 are not valid in this alphabet.
  4. Download: Saves the result as a plain text file.

Base32 variants comparison

VariantAlphabetUse case
Base32 (RFC 4648 §6)A-Z 2-7General encoding, TOTP secrets
Base32hex (RFC 4648 §7)0-9 A-VSort-preserving encoding
Crockford Base320-9 A-Z (no I,L,O,U)ULIDs, human-readable IDs

Base32 in Python

The snippet below encodes UTF-8 bytes as RFC 4648 §6 Base32 with CPython base64.b32encode and reads them back with b32decode. That is the same A–Z 2–7 alphabet and = padding this page writes for text. Node has no stdlib Base32 encoder — Buffer encodings are hex, base64, and base64url, not this alphabet. For the 0–9 A–V sibling, see Base32hex. For how Base32 compares to hex and Base64, see Hex vs Base64 vs Base32: RFC 4648 Encodings.

Python with base64.b32encode

Encode UTF-8 first — a str is not a bytes-like object. b32encode returns bytes in uppercase with padding:

import base64

encoded = base64.b32encode(b'foobar')
# b'MZXW6YTBOI======'

decoded = base64.b32decode(encoded)
# b'foobar'

Default b32decode is stricter than this page. Lowercase letters raise binascii.Error unless you pass casefold=True (this decoder always accepts both cases). Missing padding also raises unless you restore it first — s + '=' * (-len(s) % 8) makes an unpadded MZXW6YTBOI decode the same way this page does. Spaces are rejected here too unless you strip them; this page strips whitespace before decoding. Leave map01 as None so digits 0 and 1 stay invalid, matching the A–Z 2–7 alphabet. b32hexencode is RFC 4648 §7 (0–9 A–V), not this tool. Crockford Base32 (no I, L, O, U) belongs on the ULID generator. Alphabet details are in RFC 4648 Base32 vs Base32hex: Alphabet and Sort Order.

Base32 in the shell

Text encode on this page converts UTF-8 bytes with the RFC 4648 §6 alphabet (A–Z 2–7) and = padding, and does not wrap. GNU coreutils base32 uses that same alphabet. Coreutils 8.31+ basenc --base32 is documented as the same program (RFC 4648 section 6). Both wrap at 76 characters by default; pass -w 0 to match this page. echo appends a newline, so use printf to match this page's encoding of foobar. macOS ships base64 but neither base32 nor basenc. Homebrew coreutils installs gbase32 and gbasenc. OpenSSL has openssl base64, not a Base32 encoder. These commands are RFC 4648 §6, not Crockford Base32 or Base32hex.

GNU base32 (Linux)

Coreutils base32 reads a file or stdin. Decode with -d. GNU -i means --ignore-garbage on decode — it is not an input-file flag:

# Text without a trailing newline (same as this page)
printf 'foobar' | base32 -w 0
# MZXW6YTBOI======

printf 'MZXW6YTBOI======' | base32 -d
# foobar

GNU basenc (Linux)

Coreutils 8.31+ basenc --base32 is the same RFC 4648 §6 encoder as base32 (same as 'base32' program). Decode with -d. GNU -i means --ignore-garbage on decode — it is not an input-file flag. Sibling --base16 / --base32hex / --base64url flags live on those tool pages, not here:

# Text without a trailing newline (same as this page, and the same as base32 -w 0)
printf 'foobar' | basenc --base32 -w 0
# MZXW6YTBOI======

printf 'MZXW6YTBOI======' | basenc --base32 -d
# foobar

Default GNU decode is stricter than this page. Lowercase letters fail with base32: invalid input or basenc: invalid input — this decoder always accepts both cases. -i skips non-alphabet bytes as garbage; it does not casefold, so mzxw6ytboi====== still fails. Missing padding is not optional: unpadded MZXW6YTBOI writes fooba from the first eight characters, then the remaining OI errors. Restore = padding to a multiple of 8 first (MZXW6YTBOI======). This decoder accepts optional padding. Extra = after a complete group (MZXW6YTBOI=======) decodes the group, then errors. Newlines in the encoded stream are allowed; other non-alphabet bytes need -i. Empty stdin encodes or decodes to empty and exits 0; Encode and Decode on this page stay disabled until there is text. Homebrew coreutils installs gbase32 and gbasenc. For Python on macOS or Windows, use the base64.b32encode block above. Alphabet details are in RFC 4648 Base32 vs Base32hex: Alphabet and Sort Order.

FAQ

Does this tool upload my text?
No. All encoding and decoding runs in your browser using JavaScript. Nothing is sent to a server.
What alphabet does Base32 use?
RFC 4648 §6 Base32 uses A-Z and 2-7 (32 characters total), avoiding look-alike characters like 0/O and 1/I/l. Padding uses = characters to make the encoded string a multiple of 8.
Is Base32 decoding case-sensitive?
No. This decoder accepts both uppercase and lowercase letters. MZXW6YTBOI====== and mzxw6ytboi====== decode to the same result.
Is padding required for decoding?
No. This decoder accepts optional padding per RFC 4648 §3.2/§3.3. Both MZXW6YTBOI====== and MZXW6YTBOI decode correctly.
What is the difference between Base32 and Base32hex?
Base32 uses A-Z 2-7. Base32hex (RFC 4648 §7) uses 0-9 A-V, which preserves sort order. Use Base32hex when lexicographic sorting matters.
Is this the same as Crockford Base32?
No. Crockford Base32 uses 0-9 A-Z excluding I, L, O, U and is used in ULIDs. RFC 4648 Base32 is a different alphabet. Use our ULID tool for Crockford encoding.

Related