About Hex Converter
Hexadecimal writes each byte as two characters from 0-9 and a-f. It is the standard way to show bytes that are not text - hashes, keys, binary dumps, colour values, memory addresses - because the mapping is exact, position-aligned and trivially readable: two hex characters is always precisely one byte.
That fixed ratio is what makes hex useful for diagnosis in a way Base64 is not. You can count bytes by eye, spot that a 32-byte key was pasted as 64 characters rather than 32, see a UTF-8 BOM as ef bb bf at the start of a file, or notice that a supposed 16-byte IV is only 15 bytes long. The cost is size: hex is exactly twice the length of the bytes, against Base64's 33% overhead.
The commonest confusion here is exactly that length relationship. A 256-bit key is 32 bytes and therefore 64 hex characters - so a config value that is 32 characters long is a 16-byte key, not a 32-byte one, and will produce AES-128 where you expected AES-256. Crypto libraries then fail with an unhelpful key-length error.
Formatting varies and none of it changes the value: uppercase or lowercase, a 0x prefix, spaces or colons between bytes (as in MAC addresses and certificate fingerprints), or a continuous string. Hex digests are also case-insensitive as values but not as strings, so normalise case before comparing two of them.
Conversion runs in your browser and nothing is transmitted.
How to use the Hex Converter
- Paste text to convert to hex, or hex to convert back - separators, 0x prefixes and mixed case are tolerated.
- Check the byte count against what you expect: divide the hex length by two.
- Copy the result in the format the receiving system wants - continuous, colon-separated, or 0x-prefixed.
- When comparing two hex digests, normalise case first so a difference in capitalisation is not mistaken for a difference in value.
Examples
-
Text
UUID Studio -
Hex
555549442053747564696f
Hex Converter in code
The same operation this tool performs, in the languages you are most likely to need it.
const toHex = (bytes) =>
[...new Uint8Array(bytes)].map((b) => b.toString(16).padStart(2, "0")).join("");
const fromHex = (hex) => {
const clean = hex.replace(/^0x/i, "").replace(/[\s:-]/g, "");
if (clean.length % 2) throw new Error("odd number of hex digits");
return Uint8Array.from(clean.match(/../g).map((h) => parseInt(h, 16)));
};
// Text <-> hex needs an explicit UTF-8 step
const hex = toHex(new TextEncoder().encode("café")); // "636166c3a9"
console.log(new TextDecoder().decode(fromHex(hex)));
// padStart(2, "0") is essential - without it, byte 0x0a
// becomes "a" and the whole string shifts by one character.
Buffer.from("hello", "utf8").toString("hex"); // "68656c6c6f"
Buffer.from("68656c6c6f", "hex").toString("utf8"); // "hello"
// Check a key length before handing it to a cipher
const key = Buffer.from(process.env.KEY_HEX, "hex");
if (key.length !== 32) {
throw new Error(`Expected 32 bytes (64 hex chars), got ${key.length}`);
}
// Buffer's hex decoder stops silently at the first invalid character
// rather than throwing - validate with /^[0-9a-f]+$/i first.
b"hello".hex() # '68656c6c6f'
bytes.fromhex("68656c6c6f") # b'hello'
# Readable grouping
b"hello".hex(" ") # '68 65 6c 6c 6f'
b"hello".hex(":", 1) # '68:65:6c:6c:6f'
# fromhex tolerates whitespace but not 0x or colons
bytes.fromhex("68 65 6c") # works
bytes.fromhex("68:65".replace(":", ""))
# Inspect a file's first bytes to identify it
with open("f.bin", "rb") as f:
print(f.read(8).hex(" ")) # ef bb bf -> UTF-8 BOM
# Text -> hex
printf '%s' "hello" | xxd -p
# Hex -> bytes
echo "68656c6c6f" | xxd -r -p
# A proper hex dump with offsets and ASCII
xxd file.bin | head
# Random key as hex, correct length for AES-256
openssl rand -hex 32 # 64 characters = 32 bytes
When you need this
- Checking whether a key or IV in a config file is the right number of bytes.
- Reading the first bytes of a file to identify its format or spot a BOM.
- Converting between a hex digest and the Base64 form another system reports.
- Inspecting the exact bytes of a string to find an invisible or non-ASCII character.
- Producing a colon-separated fingerprint to compare against a certificate.
Common problems and what causes them
- Confusing hex character count with byte count
- Two hex characters is one byte. A 256-bit key is 32 bytes and 64 hex characters, so a 32-character value is a 16-byte key and will give you AES-128. This is the most common cause of 'invalid key length' errors.
- Missing zero padding
- Byte 0x0a must be written as '0a'. Formatting without padStart or %02x produces 'a', which shifts every subsequent character and corrupts the whole string. The result is usually an odd-length hex string.
- Odd number of hex digits
- Hex must come in pairs. An odd length means the string was truncated, or a byte lost its leading zero. Find where rather than padding the end, because padding the wrong end changes every byte.
- Uppercase versus lowercase comparison
- A3F1 and a3f1 are the same value and different strings, so a plain equality check on two digests fails. Normalise case before comparing.
- 0x prefixes and separators reaching the parser
- Most decoders reject 0x, colons and spaces. Strip them first - MAC addresses, certificate fingerprints and debugger output all carry separators that the receiving parser will not accept.
- Hex string used directly as a key
- Passing the 64-character text of a hex key to a cipher makes a 64-byte key from the ASCII characters, not the 32 bytes they represent. Decode hex to bytes first.
FAQ
- How many hex characters is a 256-bit key?
- 64. Divide bits by 8 for bytes (32), then multiply by 2 for hex characters. Getting this wrong in either direction is the usual cause of key-length errors in crypto libraries.
- Hex or Base64 - which should I use?
- Hex when a human needs to read, count or compare bytes: exactly two characters per byte, position-aligned, easy to eyeball. Base64 when size matters, since it adds 33% against hex's 100%. Hashes and keys are conventionally hex; payloads and binary blobs are conventionally Base64.
- Is hex case-sensitive?
- Not as a value - A3F1 and a3f1 are identical. It is case-sensitive as a string, so normalise before comparing. Lowercase is the usual convention for digests; uppercase is common in Windows tooling and certificate fingerprints.
- Why does my hex string have an odd number of characters?
- Something is wrong: hex always comes in pairs. Either the string was truncated, or a byte was formatted without its leading zero. Identify where the missing digit belongs rather than padding, because padding the wrong end shifts every byte.
- What is the 0x prefix for?
- It marks a literal as hexadecimal in source code and debugger output. It is not part of the value, and most hex decoders will reject it, so strip it before parsing.
- Spaces in hex?
- Decoder accepts continuous hex pairs; remove separators before decoding.