Converting Base64 to Hex: Reading the Raw Bytes Underneath
How to convert Base64 to hex by decoding to raw bytes first, why hex is twice as long, and where this byte-level view matters for keys, hashes and certificates.
Converting Base64 to Hex: Reading the Raw Bytes Underneath
Base64 and hexadecimal look like two unrelated string formats, but they are not. They are two different ways of writing the exact same thing: a sequence of raw bytes. A byte is a number from 0 to 255, and both encodings are just notations for those numbers. Base64 writes them densely, three bytes at a time. Hex writes them spaciously, one byte per pair of digits. Convert from one to the other and not a single byte changes — only the way you spell it.
That distinction sounds academic until you are staring at an API response that hands you a signature in Base64 while the verifier on your desk wants hex. So this post walks through what actually happens during a Base64 to hex conversion, why a correct converter always routes through the raw bytes, and the handful of debugging moments where the hex view earns its keep.
Both Encodings Spell the Same Bytes
Here is the single most important point, and it is worth stating plainly: Base64 and hex encode the same underlying bytes. You do not "translate" Base64 into hex the way you translate French into German. You decode the Base64 back into the byte array it always represented, and then you print each of those bytes as two hex digits. The byte array in the middle is the real value; both encodings are surface notation.
That is also why the conversion is exact. There is no rounding, no charset, no information lost. If you feed in a Base64 string that represents three specific bytes, you get those three bytes out as six hex characters, every time. A converter that works this way will round-trip a PNG header, an AES key, or a DER certificate without disturbing a single bit, because it never treats the data as text.
Why You Go Through the Bytes, Not the Text
The tempting shortcut — and the one that quietly corrupts data — is to decode Base64 to a string and then re-encode that string as hex. This works fine right up until the bytes are not valid text.
Take the byte 0xff. It is a perfectly legal byte. It is also not a valid standalone UTF-8 character. A converter that decodes Base64 into a text string first will hit 0xff, fail to interpret it, and substitute a replacement character or mangle the surrounding sequence. Your hex output is now wrong, and you will not notice until the decrypt fails an hour later.
The correct path skips text entirely. The Base64 to hex converter decodes the Base64 straight into a numeric byte array, then renders that array as hex. No UTF-8 step exists anywhere in the pipeline, so a non-printable byte is never asked to be a character. It is just the number 255, written as ff. Binary data — images, keys, hashes — survives precisely because nothing ever tries to read it as a sentence.
A Worked Example
Let us convert the Base64 string SGVsbG8= to hex by hand, so the byte-level path is concrete.
First, decode the Base64. Base64 packs three bytes into four characters, and the trailing = signals padding. SGVsbG8= decodes to five bytes: 72, 101, 108, 108, 111. Those happen to be the ASCII codes for Hello, but the converter does not care about that — it just sees five numbers.
Now print each byte as two hex digits:
72 -> 48
101 -> 65
108 -> 6c
108 -> 6c
111 -> 6f
So SGVsbG8= becomes the hex string 48656c6c6f, or 48 65 6c 6c 6f if you group it by byte. Five bytes in, ten hex characters out. The grouped form is the one I reach for when I am eyeballing data, because it lines up with how every hex editor and packet capture shows bytes.
The Density Difference, and Why It Matters
Notice that the same five bytes took 8 characters in Base64 (SGVsbG8=) and 10 in hex (48656c6c6f). That gap is not an accident; it is the whole reason both formats exist.
Base64 uses an alphabet of 64 symbols, so each character carries 6 bits of information. Four characters hold 24 bits, which is exactly three bytes. That density is why Base64 is the format of choice for transport: stuffing a binary attachment into an email, embedding an image in a data URL, or wedging a token into JSON. It is roughly 33% larger than the raw bytes, which is about as tight as a text-safe encoding gets.
Hex uses an alphabet of 16 symbols, so each character carries only 4 bits. Two characters make one byte, so hex is always exactly twice the byte count — 100% overhead. You would never email a file as hex. But that fixed, predictable, one-byte-per-pair layout is exactly what you want when you are inspecting data. Every byte sits at a known offset, magic numbers are instantly recognizable, and there is no padding arithmetic to do in your head. Base64 optimizes for size on the wire; hex optimizes for the human reading it.
Where the Hex View Pays Off
The conversion shows up almost entirely in cryptography and binary debugging, and the pattern is always the same: a value arrives in one notation and the next tool wants the other.
- Moving a key between tools. A language library prints an AES key as Base64, but the OpenSSL command you are scripting expects
-Kwith a hex string. Convert to no-separator lowercase hex and the 32-byte key drops in as 64 characters. Because the conversion is byte-for-byte, you never spend an afternoon chasing a "bad decrypt" caused by a silent encoding change. - Checking a signature. A JWT signature is URL-safe Base64 with no padding. You computed the expected HMAC elsewhere and hold it as hex. Convert the signature segment to hex and compare digit by digit — if one byte differs, you know exactly where instead of squinting at two unlike-looking strings.
- Identifying a mystery blob. A config row holds a Base64 value and you have no idea what it is. Convert to space-grouped hex and read the first few bytes:
89 50 4e 47is a PNG,ff d8 ffis a JPEG,25 50 44 46is a PDF. The hex view turns an opaque string into something you recognize at a glance.
I keep this conversion close because it has saved me from the worst class of bug — the kind where two values are supposed to be equal and the tools insist they are not. Once both are in hex, byte alignment is obvious. The mismatch is never a mystery for long: it is a wrong Base64 alphabet (standard +// versus URL-safe -/_), or a dropped leading zero that turned a clean byte into an odd-length hex run. Both are visible the instant you look at the bytes instead of the notation.
Getting the Conversion Right
Two details trip people up. The first is the Base64 alphabet. Standard Base64 uses + and /; URL-safe Base64 swaps them for - and _ and usually drops the = padding. JWTs and many web tokens are URL-safe, while most other Base64 is standard. Feed a URL-safe string to a standard decoder and the - reads as an illegal character. Match the mode to the source.
The second is hex on the way back. Each byte is exactly two hex digits, so a valid hex string always has an even length. Drop a leading zero — write f where you meant 0f — and you get an odd digit count that cannot map to whole bytes. A good tool rejects it and tells you the count rather than guessing.
If your data is genuinely text rather than binary, you may instead want a plain Base64 encoder and decoder that gives you readable output. But the moment the payload is a key, a hash, a signature, or any binary blob, go through the bytes and read them in hex. That is the view that tells the truth.
Made by Toolora · Updated 2026-06-13