Uttir
By Uttir 6 min read

Base64 vs Base64url vs Base32 vs Hex: When to Use Each

Four encodings that all turn binary into text, but with different alphabets, sizes, and URL-safety. This guide explains the differences, the use cases, and the gotchas that trip people up.

Use standard Base64 for email, MIME, PEM files, HTTP Basic Auth, and tiny data: URIs. Use Base64url for JWTs, OAuth state parameters, and anything that goes in a URL. Use Base32 for secrets you have to read or type by hand (TOTP, recovery codes, AWS access keys) because the alphabet has no 0/O, 1/l/I confusion. Use Hex for hashes, cryptographic keys, and anywhere you want a 2× size increase that is still easy to read in any text editor.

If you have ever looked at a JWT, a TOTP secret, or a crypto hash and wondered why it looks the way it does, the answer is "encoding choices". There is no single right way to turn binary into text — the right choice depends on where the encoded value will live (URL? typed by hand? printed on a label?) and what kind of errors you are trying to prevent. This guide walks through the four most common text encodings developers encounter, the alphabet each one uses, the size cost of each, and the use cases that map cleanly to each.

The shared problem

Computers store everything as bytes. But a lot of the world expects text — URLs, email bodies, JSON, config files, typewriters. If you need to ship arbitrary bytes through a text-only channel, you have to encode them. The four encodings below all solve that problem, with different trade-offs:

  • Alphabets — what characters are used. Bigger alphabet = more compact output.
  • Size cost — how much bigger the encoded string is than the original bytes.
  • Human-readability — case-sensitive? ambiguous characters? easy to type?
  • URL-safety — does the encoding contain characters that have to be escaped in URLs?

Hex: the simple, readable one

Hex (base-16) is the simplest encoding: every byte becomes two characters from 0-9 and a-f (or A-F). It is not a base-N encoding in the same sense as the others — it is just "show the byte's value in two hex digits".

The trade-offs:

  • Alphabet0-9 a-f. Case is conventional, not significant.
  • Size — exactly 2× the original. A 32-byte SHA-256 hash becomes 64 hex characters.
  • URL-safe — yes, every character is URL-safe.
  • Human-readable — yes. Easy to copy from logs, easy to read on a screen, easy to type.

Use it for: cryptographic hashes (SHA-1, SHA-256, MD5 — though MD5 is broken for security), cryptographic key fingerprints, color codes in CSS (#ff8800 is hex for an RGB color), MAC addresses, and anywhere you want the output to be twice the size of the input and trivially readable.

The big downside: 2× overhead is the worst of the four. If you are encoding large amounts of data and don't need hex for any other reason, you can do better.

Base64: the workhorse

Base64 is the encoding you will see most often. It uses a 64-character alphabet — 26 uppercase + 26 lowercase + 10 digits + 2 symbols (+ and /) — plus = for padding. Every 3 bytes of input become 4 characters of output, giving the 33% size cost you have probably heard quoted.

The trade-offs:

  • AlphabetA-Z a-z 0-9 + /, with = for padding.
  • Size — 4/3 of the input, plus padding to a multiple of 4.
  • URL-safeno. The +, /, and = characters are special in URLs and need percent-encoding.
  • Human-readable — yes, but the alphabet has lookalikes (0 O o, 1 l I) that can confuse manual transcription.

Use it for: email (MIME attachments), PEM-encoded certificates and keys, HTTP Basic Auth headers, tiny data: URIs for inline images, and anywhere you are encoding binary for storage or transport in a text-only channel that is not a URL.

The big downside: Base64 is not encryption. It is encoding. Anyone can decode it instantly. Treat any "encoded password" or "obfuscated token" stored as Base64 as plain text from a security perspective.

Base64url: Base64 for URLs

Base64url is the same algorithm as standard Base64, with two character substitutions and a padding rule that makes the output safe to drop into a URL without escaping:

  • + becomes -
  • / becomes _
  • Padding = is usually dropped (URLs already have length and structure that make padding unnecessary)

The trade-offs:

  • AlphabetA-Z a-z 0-9 - _, padding optional.
  • Size — same as standard Base64 (4/3).
  • URL-safeyes. Every character is in the URL-safe set, and you can drop padding without losing data.

Use it for: anything that goes in a URL — JWTs, OAuth state and PKCE parameters, signed cookies, signed URLs in cloud storage, signed webhook payloads, filename-safe tokens.

The gotcha: standard Base64 decoders will not accept Base64url input. If you have a JWT in a URL and try to feed it to a standard Base64 decoder, it will either reject it or silently produce garbage. Use a tool that knows about the URL-safe variant — most modern JWT libraries handle it transparently, but a plain Base64 decoder does not.

Base32: the human-friendly one

Base32 is designed for the opposite problem of Base64: when a human might have to read or type the encoded value, Base32's smaller, simpler alphabet is worth the extra size. The standard Base32 alphabet is A-Z 2-7 (32 characters), and the output is padded to a multiple of 8 with =. The size cost is 8/5 = 60% bigger than the input.

The trade-offs:

  • AlphabetA-Z 2-7. All uppercase, no lowercase, no lookalike characters (0 O 1 l I are excluded from the alphabet).
  • Size — 8/5 of the input (60% bigger).
  • URL-safe — yes, every character is URL-safe (modulo the padding).
  • Human-readableexcellent. The 32-character alphabet is easy to read aloud, type on a phone keyboard, or transcribe from a piece of paper. This is the reason Base32 exists.

Use it for: TOTP secrets (the codes from Google Authenticator — the QR code you scan encodes a Base32 secret), cryptographic key fingerprints you might want to compare by eye, AWS access key IDs, recovery codes, anything a person might need to read or transcribe.

The gotcha: the larger size means Base32 is the wrong choice for high-volume data. Use it for short, important values (a 32-byte secret, a 16-character key) where readability matters more than compactness. Do not use it to encode images.

How to pick, in one table

EncodingSize costURL-safeHuman-friendlyReach for it when
HexYesYesHashes, fingerprints, color codes
Base644/3 (33%)NoOKEmail, PEM, Basic Auth, data: URIs
Base64url4/3 (33%)YesOKJWTs, OAuth, signed URLs, anything URL-bound
Base328/5 (60%)YesExcellentTOTP secrets, recovery codes, manual transcription

The cross-decoding gotcha

Most encoding mistakes are not picking the wrong algorithm. They are feeding the wrong input to the right algorithm. Three rules that catch 90% of the bugs:

  1. Check the alphabet. If the input contains + or /, it is standard Base64. If it contains - or _, it is Base64url. If it contains only uppercase letters and the digits 2–7, it is Base32. If it contains only 0-9 a-f, it is Hex.
  2. Check the length. A valid Base64 string is a multiple of 4 in length (after stripping padding). A valid Base32 string is a multiple of 8. Hex is always even. If the length is off, padding has been stripped (or added) and you need to fix it before decoding.
  3. Strip whitespace before decoding. Some formats (MIME email, in particular) insert line breaks every 76 characters. Most decoders do not accept whitespace, and will fail silently or with a cryptic error.

Try them in the browser

For quick experiments, a browser-based encoder/decoder is the fastest feedback loop. The Base64 encoder and Base64 decoder are the standard variant. The Base32 encoder/decoder covers the case where you are debugging a TOTP secret or recovery code. And the URL encoder/decoder handles the percent-encoding that often shows up alongside Base64url.

The four encodings look interchangeable at first glance, but the choice between them is one of the small decisions that separates a working integration from a security incident. Pick the encoding that matches the channel, match the alphabet the receiver expects, and remember that none of them is encryption — when the secret needs to be secret, encrypt it first, encode it second.

#encoding#base64#base32#hex#developer-tools

New tools and guides, once a week

One short email when something new ships. No tracking, no images, unsubscribe with one click.