Base64 vs Hex Encoding: Size, Byte Handling, and When to Use Each
Both turn bytes into text; the difference is how densely and conveniently they represent them.
Key takeaways
- Hex represents each byte with two digits, while Base64 groups three bytes into four characters.
- Padded Base64 has an exact length of four times the input byte count divided by three and rounded up.
- Base64url changes the alphabet, while padding requirements come from the surrounding protocol.
- Neither encoding encrypts data, validates its meaning, or makes a secret safe to publish.
Base64 and hexadecimal are reversible ways to represent bytes as text. Hex is convenient for inspecting individual bytes. Base64 is generally more compact when a text field must carry binary data.
Imagine an API returning a small binary attachment and its checksum. Base64 might represent the attachment, while hex makes the checksum easy to compare with command-line output. Both fields still need an explicit contract describing their encoding.
Neither representation changes what the original bytes mean.
Start With the Bytes
The UTF-8 bytes for Hello have these two representations:
Hex: 48656c6c6f
Base64: SGVsbG8=
Hex splits every byte into two four-bit values, each written with a digit from 0 through F.
Base64 groups bits into six-bit values and maps them to a 64-character alphabet. Standard Base64 uses letters, digits, plus, and slash. Padding completes the final group when required.
RFC 4648 specifies the alphabets and encoding rules. The surrounding protocol determines details such as permitted padding and line breaks.
Calculate the Expansion Exactly
For an input of n bytes, without separators or line wrapping:
Hex characters = 2 × n
Padded Base64 characters = 4 × ceil(n / 3)
| Input bytes | Hex characters | Padded Base64 characters |
|---|---|---|
| 1 | 2 | 4 |
| 3 | 6 | 4 |
| 32 | 64 | 44 |
| 100 | 200 | 136 |
| 1,000 | 2,000 | 1,336 |
Base64 approaches one-third expansion for larger inputs. Small inputs have proportionally more overhead because of the final group.
A 32-byte digest therefore needs 64 hex characters or 44 padded Base64 characters. Those are representations of the same digest, not different strengths of checksum.
These counts exclude JSON punctuation, transport headers, and compression.
Encode Text Into Bytes Before Encoding the Bytes
Text has a character encoding too. The number of visible characters is not necessarily the number of UTF-8 bytes.
In Node.js, make the conversion explicit:
const bytes = Buffer.from("Hello", "utf8");
const hex = bytes.toString("hex");
const base64 = bytes.toString("base64");
const restored = Buffer.from(base64, "base64");
console.log(restored.toString("utf8")); // Hello
The Node.js Buffer documentation describes these conversions.
For an image or encrypted file, keep the decoded value as bytes. Converting arbitrary binary data to a UTF-8 string can lose information because those bytes may not represent valid text.
The attachment API should define the original media type separately from its transport encoding.
Base64url Is a Related Format
Base64url replaces standard Base64’s plus and slash with hyphen and underscore. Some protocols also omit padding, but that is a protocol rule rather than an invitation to strip characters indiscriminately.
Do not lowercase Base64 values: its alphabet is case-sensitive. Hex conventions commonly permit either letter case, though a protocol may require one canonical form.
When carrying a value in a URL, follow that field’s specified representation. Choosing a URL-safe alphabet does not replace URL construction and escaping rules for the rest of the address.
Decoding Is Not Validation
A decoder may tolerate whitespace, missing padding, or other inputs that a strict protocol would reject.
Node.js also documents cases where hex decoding truncates malformed input. Successfully obtaining a byte buffer therefore does not prove the original string satisfied the application’s contract.
For the attachment, check allowed encoding syntax, encoded and decoded size limits, and the expected content format. For the checksum, check the decoded digest length.
Schema validation can describe parts of this contract, but the implementation must enforce the actual decoding behavior.
Choose the Representation the Interface Needs
Use hex when people need to inspect byte values or compare fingerprints. Use Base64 when an existing text format needs a denser binary representation.
If the interface accepts a binary HTTP body or a suitable file-upload format, encoding the file inside JSON may add unnecessary memory and size overhead. Base64 is smaller than hex, but larger than the original bytes.
Finally, encoding provides no confidentiality. A Base64 attachment is readable by anyone who can decode it. Sensitive data still requires appropriate access controls and, where needed, encryption.
For the API, document each field’s alphabet, padding, byte meaning, and limits. That agreement matters more than whether the string looks compact.
An encoded secret is still a secret, even when its representation looks unfamiliar.
More Articles Like This

JSON Schema vs TypeScript Types: Where Each Protects Your Data

Regex vs Parsing: Choosing the Right Tool for Structured Text
What Is a .dockerignore File? Build Context, Patterns, and Common Mistakes
What Is a Regular Expression? Regex Patterns Explained With Examples
