Base32hex encoder / decoder

Encode and decode Base32hex (RFC 4648 §7) using the sort-preserving 0-9 A-V alphabet.

Docify's Base32hex encoder implements RFC 4648 §7 using the 0-9 and A-V alphabet (32 characters) with = padding. Example: foobar encodes to CPNMUOJ1E8======. Unlike standard Base32, this alphabet preserves lexicographic sort order. Decoding is case-insensitive and accepts optional padding. Used in DNSSEC NSEC3 hashes. For standard Base32 (A-Z 2-7), use our Base32 tool. Nothing is uploaded.

Plain text
Base32hex output

How it works

  1. Encoding: Input text is converted to UTF-8 bytes. Each group of 5 bytes (40 bits) becomes 8 Base32hex characters using the 0-9 A-V alphabet. Padding uses = characters.
  2. Decoding: Base32hex characters are converted back to bytes. The decoder is case-insensitive and strips whitespace. Padding is optional.
  3. Sort preservation: The 0-9 A-V alphabet maintains the same ordering as the original binary data when sorted as strings.
  4. Invalid characters: W, X, Y, Z are not valid in this alphabet — they belong to standard Base32 (A-Z 2-7).

Base32 vs Base32hex alphabets

VariantAlphabetSort-preserving
Base32 (RFC 4648 §6)A-Z 2-7No
Base32hex (RFC 4648 §7)0-9 A-VYes

Base32hex in Python

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

Python with base64.b32hexencode

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

import base64

encoded = base64.b32hexencode(b'foobar')
# b'CPNMUOJ1E8======'

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

Default b32hexdecode 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 CPNMUOJ1E8 decode the same way this page does. Spaces are rejected here too unless you strip them; this page strips whitespace before decoding. Digits 0 and 1 are valid here — b32hexdecode has no map01 argument, because those characters sit in the Extended Hex alphabet and are not interchangeable with O, I, or L. b32encode is RFC 4648 §6 (A–Z 2–7), 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.

Base32hex in the shell

Text encode on this page converts UTF-8 bytes with the RFC 4648 §7 alphabet (0–9 A–V) and = padding, and does not wrap. GNU coreutils 8.31+ basenc --base32hex uses that same alphabet. It wraps 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 neither basenc nor base32. Homebrew coreutils installs gbasenc. OpenSSL has openssl base64, not a Base32hex encoder. GNU base32 is RFC 4648 §6 (A–Z 2–7), not this alphabet. These commands are RFC 4648 §7, not Crockford Base32 or standard Base32.

GNU basenc (Linux)

Coreutils basenc --base32hex 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' | basenc --base32hex -w 0
# CPNMUOJ1E8======

printf 'CPNMUOJ1E8======' | basenc --base32hex -d
# foobar

Default GNU decode is stricter than this page. Lowercase letters fail with basenc: invalid input — this decoder always accepts both cases. -i skips lowercase as garbage; it does not casefold. Missing padding is not optional: the complete 8-character group CPNMUOJ1 decodes as fooba, then the remaining E8 errors. Restore = padding to a multiple of 8 first. This decoder accepts optional padding. Newlines in the encoded stream are allowed; other non-alphabet bytes need -i. For Python on macOS or Windows, use the base64.b32hexencode 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 is the difference between Base32 and Base32hex?
Base32 uses A-Z 2-7. Base32hex uses 0-9 A-V. The hex variant preserves lexicographic sort order — if A < B as binary, then encode(A) < encode(B) as strings. This is useful for DNSSEC NSEC3 hashes.
Is Base32hex decoding case-sensitive?
No. This decoder accepts both uppercase and lowercase letters. CPNMUOJ1E8====== and cpnmuoj1e8====== decode to the same result.
Is padding required for decoding?
No. This decoder accepts optional padding per RFC 4648 §3.2/§3.3. Both CPNMUOJ1E8====== and CPNMUOJ1E8 decode correctly.
Is this the same as hexadecimal encoding?
No. Base32hex and hexadecimal (Base16) are different. Base32hex uses 5 bits per character (32 values: 0-9 A-V), while hex uses 4 bits per character (16 values: 0-9 A-F). Base32hex is more compact.
What is Base32hex used for?
Base32hex is specified in RFC 4648 §7 and used in DNSSEC (NSEC3 owner names) where sort preservation is required. It is less common than standard Base32.

Related