To convert hex to Base64 manually, group every three input bytes into 24 bits, split those bits into four 6-bit chunks, and look up each chunk's index in the standard Base64 alphabet defined by RFC 4648. When the final group contains only one or two bytes, add zero pad bits on the right to complete the last 6-bit chunk, then append one or two '=' characters so the total character count stays a multiple of four. The reverse path, Base64 back to hex, is the inverse: every four Base64 characters decode into three bytes, with strict validators also requiring that any zero pad bits really are zero and that '=' padding appears only at the end of the string. Both encodings are lossless representations of the same byte sequence, so a clean round trip tells you only that the bytes survived intact; it says nothing about whether the data is encrypted, compressed, signed, or meaningful. This guide walks through the manual mechanics with the canonical RFC 4648 test vectors, points out where hand calculation typically goes wrong, and shows how to run the same conversion through a browser-based tool when the manual approach stops being practical.

how to convert hex to base64 manually
how to convert hex to base64 manually

Why Hex and Base64 Look So Different

Hexadecimal, the encoding most programmers write as "hex", is just a way to spell raw bytes using two digits per byte. Each digit carries four bits of information, so the string 66 really means the byte 01100110, the string 666f means two bytes 01100110 01101111, and so on. A 16-byte hash is therefore always 32 hex characters long, and you can read or edit it with no special tool beyond a table of hex digits.

Base64 was designed for a different job: fitting arbitrary bytes into places that expect text. It uses a 64-character alphabet drawn from the ASCII range so the output survives copy-paste, terminals, JSON, and most legacy protocols. Because 64 is not a power of two, every Base64 character carries six bits of information rather than four, and the standard groups raw bytes into blocks of three (24 bits) before slicing them into four output characters. That extra density, roughly 33 percent less overhead than hex, is why Base64 shows up in MIME email, JWT tokens, and data URLs.

The Core Rule: 3 Bytes Become 4 Base64 Characters

The whole manual conversion collapses to one rule: every three input bytes produce exactly four Base64 characters. The standard alphabet (per RFC 4648) lists the 26 uppercase letters, the 26 lowercase letters, the digits 0 through 9, plus '+' and '/', in that order. Indices 0 through 25 map to A through Z, 26 through 51 map to a through z, 52 through 61 map to 0 through 9, 62 is '+', and 63 is '/'.

If the final group contains only one or two bytes, the encoder pads the bit stream with zeros on the right to fill a 6-bit chunk, then appends '=' signs so the total length stays a multiple of four. One leftover byte produces two characters plus two '=' signs; two leftover bytes produce three characters plus one '=' sign. The trailing zero pad bits are not free: a strict decoder refuses any string where those pad bits are set to 1, because that would create a second, non-canonical spelling of the same bytes.

The canonical test vectors from RFC 4648 Section 10 make the relationship easy to verify by hand:

ASCII inputHex bytesBase64 outputDecoded bytes
f66Zg==1
fo666fZm8=2
foo666f6fZm9v3
foob666f6f62Zm9vYg==4
fooba666f6f6261Zm9vYmE=5
foobar666f6f626172Zm9vYmFy6

Each row takes the raw bytes on the left, packs them into 6-bit chunks, and emits the four-character Base64 group. The empty input (zero bytes) becomes the empty Base64 string. Anything you produce by hand should match one of these rows before you trust it.

How to Convert Hex to Base64 Manually

  1. Validate the hex string. Confirm every character is a hex digit, the total length is even, and there is no 0x prefix, whitespace, underscore, or colon. The string 66 6f is rejected; the string 666f is accepted and represents two bytes.
  2. Translate each pair into one byte. Concatenate the bits: 66 becomes the byte 01100110, 6f becomes 01101111, and so on. Keep the bytes in order.
  3. Group the bytes into blocks of three. Three bytes give 24 bits, which is exactly four 6-bit Base64 chunks. If the tail has one or two leftover bytes, set them aside for the padding step.
  4. Split each 24-bit block into four 6-bit chunks and translate. Read the bits from left to right, six at a time, and look each chunk up in the standard alphabet: 0 to 25 gives A to Z, 26 to 51 gives a to z, 52 to 61 gives 0 to 9, 62 is '+', 63 is '/'.
  5. Worked example for one byte. Take hex 66. The byte is 01100110. Pad on the right with zeros to reach 12 bits, giving 011001 100000. The first chunk is binary 011001, which is decimal 25, which is the letter 'Z'. The second chunk is binary 100000, which is decimal 32, which is the letter 'g'. The output so far is "Zg".
  6. Apply padding to the final group. One leftover byte produced two real characters, so append two '=' signs to reach a multiple of four: Zg==. Two leftover bytes produce three real characters plus one '=' sign. Three leftover bytes need no '='.
  7. Verify the zero pad bits are really zero. If you produced ZgA= instead of Zg==, the trailing pad bits would be non-zero, and a strict decoder will reject that spelling. A clean manual conversion always produces the canonical form shown in the RFC table.

Where Manual Conversion Breaks Down

Manual conversion is a useful exercise for learning the encoding, but it rarely scales to real work. The first trap is nibble alignment. A hex string with an odd number of digits has no defined last byte, so anything you produce will quietly shift by half a byte and the result will fail the next round trip. The second trap is the base64url profile, which swaps '+' and '/' for '-' and '_' and often drops the '=' padding entirely. Many command-line tools accept base64url under that separate name; if you paste such a string into a strict standard Base64 decoder, it fails immediately because the alphabet does not match.

Whitespace is a third trap. RFC 4648 canonical Base64 has no embedded newlines, while MIME email and many CLI encoders insert a line break every 76 characters. A strict converter refuses line-wrapped input to avoid guessing which profile you meant, which can look like an unhelpful error until you remove the wraps. Leading zeros are a fourth trap. The hex string 0066 is two bytes (00000000 01100110), not the same as 66 (one byte). Skipping leading zeros silently shortens the payload and breaks hashes, signatures, and exact cache keys.

Finally, non-canonical padding lets two different Base64 strings decode to the same bytes. The string Zg== and a (wrong) variant where the trailing pad bits were set to 1 both represent the same byte, but only the canonical form survives round-trip comparison against a specification or a signed token. Manual calculation is exactly where those errors get introduced and never noticed.

Run the Conversion With the Base64 to Hex Converter

When you need the answer rather than the lesson, the Base64 to Hex Converter enforces the same rules the manual method is supposed to follow: standard RFC 4648 Base64 with required '=' padding, strict two-digits-per-byte hex with no 0x prefix, and a byte-level validation that rejects non-canonical pad bits. The conversion runs locally in the browser, the input never leaves your machine, and the input limit is 500,000 decoded bytes per run. Conversion uses numeric byte arrays rather than browser text coercion, malformed input produces a specific error without a partial result, and the copy action copies only the converted value.

To convert hex to Base64 with it:

  1. Choose the "hex to Base64" direction and confirm your input is standard RFC 4648 Base64 or two-digits-per-byte hex, not base64url or a line-wrapped MIME variant.
  2. Paste the hex string without spaces, 0x prefixes, underscores, or separators. If the hex begins with leading zero bytes, leave them in: 0066 is two bytes, not one.
  3. Run the conversion, check the reported byte length against what you expected, verify that leading zeros show as 00 in the result, then copy the exact Base64 output.

For code-oriented readers, the same conversion can be implemented with library calls such as binascii.hexlify and base64.b64encode; a worked walkthrough of that path is in From Hex to Base64 in Python Without Breaking the Bytes. The browser tool is faster for ad-hoc inspection and removes every place a hand calculation can slip.