ctype_xdigit
Checks whether every character in a string is a valid hexadecimal digit.
ctype_xdigit(mixed $text): bool- Added in PHP 4.0.4
Parameters
| Parameter | Type | Description |
|---|---|---|
$text | mixed | The string to test. Every byte must be 0-9, a-f or A-F for the result to be true. An int between -128 and 255 is interpreted as an ASCII codepoint, which is why non-string arguments are deprecated as of PHP 8.1. |
Return value
booltrue if every character in text is a hexadecimal digit — a decimal digit or a character from [A-Fa-f] — false otherwise. An empty string always returns false.
Errors
Never throws. A non-string argument raises an E_DEPRECATED notice as of PHP 8.1; values that are neither string nor int return false.
Changelog
- PHP 8.1Passing a non-string argument is deprecated. Ints between -128 and 255 are still read as ASCII codepoints, so cast to string or call chr() explicitly, depending on the behaviour you want.
ctype_xdigit() validates that a string is made only of hexadecimal digits: 0-9, a-f and A-F, in any mix of case. It is the guard you want before calling hexdec() or hex2bin(), both of which are lenient in ways that hide bugs — hexdec() silently ignores invalid characters, and hex2bin() emits a warning and returns false on bad input.
When to reach for it
- Checking a CSS colour such as
#1A2B3Cafter stripping the hash. - Verifying a hash, nonce, signature or hex-encoded token before decoding it.
- Validating a MAC address or UUID segment once the separators are removed.
What trips people up
Prefixes and separators are not hex digits. ctype_xdigit('0x1A') is false because of the x, and a UUID with its dashes fails until you strip them with str_replace('-', '', $uuid).
Length is your responsibility. A three-character string passes this test but is not a valid byte sequence for hex2bin(), which needs an even number of characters — always check strlen($s) % 2 === 0 as well.
Example
When to use it
- Validating a hex colour code from a form before storing it
- Confirming an API signature is well-formed hex before comparing it
- Checking a UUID or MAC address once its dashes and colons are removed
Frequently asked questions
Does ctype_xdigit accept the 0x prefix?
No. The letter x is not a hexadecimal digit, so ctype_xdigit('0x1A') returns false. Strip the prefix first, for example with str_starts_with and substr.
Is ctype_xdigit case sensitive?
No. Both a-f and A-F are accepted, so 'deadBEEF' passes. Normalise with strtolower or strtoupper afterwards if you need a consistent stored form.
What is the difference between ctype_xdigit and ctype_digit?
ctype_digit accepts only 0-9, while ctype_xdigit also accepts the letters a-f in either case. Every string that passes ctype_digit also passes ctype_xdigit.
More examples
Guarding a hex2bin call
Prints "decoded bytes: 4", then "normalised: DEADBEEF", then false for the string ending in 'g'. The even-length test matters because hex2bin warns and returns false on an odd number of characters.
<?php
$token = 'deadBEEF';
if (ctype_xdigit($token) && strlen($token) % 2 === 0) {
echo 'decoded bytes: ', strlen(hex2bin($token)), "\n";
echo 'normalised: ', strtoupper($token), "\n";
}
var_dump(ctype_xdigit('deadbeeg'));Validating a UUID after stripping dashes
Prints false then true. The raw UUID fails because the dashes are not hex digits, so the separators must be removed before the test, and the length check confirms all 32 nibbles are present.
<?php
$uuid = '550e8400-e29b-41d4-a716-446655440000';
$plain = str_replace('-', '', $uuid);
var_dump(ctype_xdigit($uuid));
var_dump(ctype_xdigit($plain) && strlen($plain) === 32);
Discussion