Signature
hex2bin(string $string): string|falsePurpose
hex2bin() turns a string of hexadecimal digits back into the raw bytes those digits describe. Every pair of hex characters becomes one byte, so "48" becomes the single character H. It is the inverse of bin2hex(), and it is commonly used for tokens, hashes, keys and binary identifiers that are stored or transmitted as readable text.
The name is easy to misread. The function does not convert a hexadecimal number into a binary number such as 11111111. It decodes hex-encoded data into a byte string. If you want number-base conversion, use base_convert() instead.
Signature
The function is available in PHP 5.4 and later, including PHP 8.4.
Parameters and defaults
$string: the hexadecimal representation of the data. It has no default, so it is required.
The input must contain an even number of characters, and each character must be a hexadecimal digit (0-9, a-f or A-F). Upper and lower case may be mixed. Spaces, a 0x prefix, colons and other separators are not hex digits, so they make the input invalid.
Return value and failure cases
On success the function returns a string of raw bytes. The result is half as long as the input. That string may contain bytes that are not printable or not valid UTF-8, so be careful when you echo it or pass it to functions that expect text.
On failure the function returns false and raises an E_WARNING. Two situations trigger this:
- the input has an odd length;
- the input contains a character that is not a hexadecimal digit.
Because a warning is emitted, untrusted input should be checked before decoding, or the failure must be handled deliberately.
Example 1: decoding readable text
The hex below spells out an ASCII sentence. var_dump() shows both the byte length and the content.
$text = hex2bin("6578616d706c65206865782064617461");
var_dump($text);string(16) "example hex data"
The 32 hex characters become 16 bytes.
Example 2: working with non-printable bytes
Decoded data does not have to be text. Here the bytes are 0x00, 0xFF and 0x10. Inspecting them with strlen(), unpack() and bin2hex() is safer than echoing the raw string.
$bytes = hex2bin("00ff10");
echo strlen($bytes), "\n";
echo json_encode(array_values(unpack("C*", $bytes))), "\n";
echo bin2hex($bytes), "\n";3 [0,255,16] 00ff10
The round trip through bin2hex() restores the original lowercase hex.
Example 3: validating before decoding
A small wrapper can reject bad input without triggering a warning. It checks for an empty value, odd length and non-hex characters, and returns null when the input cannot be decoded. Rejecting an empty string is a choice made by this wrapper, not a rule of hex2bin().
function decodeHex(string $hex): ?string {
if ($hex === '' || strlen($hex) % 2 !== 0 || !ctype_xdigit($hex)) {
return null;
}
return hex2bin($hex);
}
echo json_encode([
decodeHex("486921"),
decodeHex("abc"),
decodeHex("zz"),
decodeHex("4A4b"),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";["Hi!",null,null,"JK"]
Mixed-case input such as 4A4b is accepted.
Edge cases
- Odd length:
"abc"cannot be split into whole bytes, so decoding fails. - Prefixes and separators:
"0xff","ff ff"and"ff:ff"are all invalid. Strip or normalize them yourself first. - Case:
"FF"and"ff"decode to the same byte. - Binary results: the returned string may hold null bytes or invalid UTF-8. Functions such as
json_encode()can refuse such data, so encode it again (for example withbin2hex()) before showing or storing it as text. - Strict comparison: always compare the result with
=== false, since a valid result is a string.
Common mistakes
- Expecting a base conversion.
hex2bin("ff")returns one byte with value 255, not the text"11111111". Usebase_convert()for number bases. - Ignoring
false. Passing the result straight into other code can hide a decoding failure. Check it explicitly. - Suppressing warnings instead of validating. The
@operator hides the message but does not make the input correct. Validating with a length check andctype_xdigit()is clearer. - Printing raw bytes. Decoded binary can corrupt terminal or browser output. Inspect it with
bin2hex()orunpack(). - Leaving formatting in the input. Whitespace, newlines or prefixes copied from logs or documents make the string invalid.
Related functions
bin2hex()converts raw bytes into hexadecimal text, the opposite direction.unpack()reads values out of a binary string.pack()builds binary strings from typed values.base_convert()converts numbers between bases.ctype_xdigit()checks whether a string contains only hexadecimal digits.
Recap
hex2bin() decodes pairs of hex digits into bytes and returns string|false. It needs even-length input made only of hex digits, otherwise it raises a warning and returns false. Validate untrusted input first, remember that the result is binary data rather than a number, and pair the function with bin2hex() for round trips.
Tested examples
$text = hex2bin("6578616d706c65206865782064617461");
var_dump($text);string(16) "example hex data"
$bytes = hex2bin("00ff10");
echo strlen($bytes), "\n";
echo json_encode(array_values(unpack("C*", $bytes))), "\n";
echo bin2hex($bytes), "\n";3 [0,255,16] 00ff10
function decodeHex(string $hex): ?string {
if ($hex === '' || strlen($hex) % 2 !== 0 || !ctype_xdigit($hex)) {
return null;
}
return hex2bin($hex);
}
echo json_encode([
decodeHex("486921"),
decodeHex("abc"),
decodeHex("zz"),
decodeHex("4A4b"),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";["Hi!",null,null,"JK"]