grapheme_strlen() counts user-perceived characters, but it requires valid UTF-8. Its result is not always an integer: invalid input can produce null, and other failures may produce false. Check the type before using the length.
Last updated: October 26, 2026.
<?php
function graphemeLength(string $text): int
{
$length = grapheme_strlen($text);
if (!is_int($length)) {
$errorCode = intl_get_error_code();
$errorName = intl_error_name($errorCode);
throw new InvalidArgumentException(
"Text is not valid UTF-8 ({$errorName})."
);
}
return $length;
}
echo graphemeLength("Café"); // 4 grapheme clustersRead the ICU error immediately after the failed internationalization call. Log the symbolic error name if needed, but do not include the original untrusted text in an exception or production log.
Treat the return type as part of the contract
The grapheme_strlen() documentation declares an int|false|null return type and requires valid UTF-8. Testing with is_int() accepts every successful length, including zero, while rejecting both documented failure values. A loose check such as if (!$length) incorrectly treats an empty string as a failure because its valid length is zero.
The intl_get_error_message() documentation explains that it describes the last internationalization error. For structured handling, capture intl_get_error_code() and convert it with intl_error_name(), as shown above. The intl extension and ICU must be available.
Choose the length that matches the rule
strlen() counts bytes. mb_strlen($text, "UTF-8") counts Unicode code points. grapheme_strlen() counts extended grapheme clusters, so a base letter plus combining mark or a multi-code-point emoji can count as one visible character. That makes grapheme length appropriate for user-facing limits, but storage and protocol limits may still be defined in bytes.
Validate or normalize text at the system boundary rather than silently deleting invalid bytes. If data arrived in another known encoding, convert from that encoding explicitly. If its origin is unknown, reject it and ask the producer to send UTF-8. Continue with fixing invalid UTF-8 in JSON, handling PHP encoding errors, and understanding Unicode normalization.