Strings7 min readExamples run on PHP 8.5.10

strlen()

Learn how PHP 8.4 strlen() counts the bytes in a string, how it behaves with UTF-8, empty strings and strict types, and which mistakes to avoid.

Signature

strlen(string $string): int

Purpose

strlen() tells you how long a string is. The important detail is the unit: it returns the number of bytes in the string, not the number of visible characters. For plain ASCII text the two numbers are the same. For text in UTF-8 they often differ.

Typical uses include checking that a token has an exact size, enforcing a byte limit before storing or sending data, and testing whether a string is empty. Because PHP strings are sequences of bytes, strlen() is also safe to use on binary data.

Signature

Parameters and defaults

  • $string: the string to measure. It is required and has no default value.

The function takes no other arguments. It does not trim, normalize or decode the string. Whatever bytes are stored in the variable are the bytes that get counted, including spaces, newlines and null bytes.

Return value and failure cases

strlen() returns an int that is zero or greater. An empty string gives 0.

The function has no "false on failure" result. The failure case is a type error. An array or an object without a string conversion is rejected with a TypeError. Scalar values such as integers are converted to strings in the default coercive typing mode, but a file that declares strict_types=1 rejects an int passed directly. Passing null is also best avoided. Built-in functions with a non-nullable parameter treat it as an empty string, but PHP 8.4 reports a deprecation notice.

Example 1: basic lengths

Spaces count like any other character, and an empty string has length zero.

Example
<?php
$values = ['abcdef', ' ab cd ', ''];
foreach ($values as $value) {
    echo strlen($value), PHP_EOL;
}
Output
6
7
0

The loop prints 6, 7 and 0, one per line. The middle value has two leading and trailing spaces plus a space between the letter pairs, so seven bytes in total.

Example 2: bytes versus characters

In UTF-8, one visible character can take from one to four bytes. The sample strings below use escape sequences so the byte content does not depend on how the file is saved.

Example
<?php
$samples = [
    'ascii' => 'PHP',
    'accented' => "caf\u{00E9}",
    'euro' => "\u{20AC}",
    'emoji' => "\u{1F600}",
];
$lengths = [];
foreach ($samples as $name => $text) {
    $lengths[$name] = strlen($text);
}
echo json_encode($lengths), PHP_EOL;
Output
{"ascii":3,"accented":5,"euro":3,"emoji":4}

The word "café" has four characters but five bytes, because the letter é takes two bytes in UTF-8. The euro sign takes three bytes and the emoji takes four. If you need a character count, use a multibyte-aware function such as mb_strlen() instead.

Example 3: binary data and strict types

A null byte is an ordinary byte for strlen(), so it does not end the count the way it would in C. Under strict typing, numbers must be converted to strings explicitly.

Example
<?php
declare(strict_types=1);

$binary = "a\0b";
$number = 12345;

echo json_encode([
    'binary' => strlen($binary),
    'number_as_text' => strlen((string) $number),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;

try {
    echo strlen($number);
} catch (TypeError $e) {
    echo get_class($e), PHP_EOL;
}
Output
{"binary":3,"number_as_text":5}
TypeError

The binary string holds three bytes. The number 12345 has five digits once cast to a string. The direct call with an int throws a TypeError because strict mode disables the implicit conversion.

Edge cases

  • Empty string: the result is 0, which makes strlen($s) === 0 a clear emptiness test.
  • Whitespace: spaces, tabs and newlines all count. Call trim() first if you want to ignore surrounding whitespace.
  • Multibyte text: the result is a byte count, so it can be larger than the number of characters a reader sees.
  • Combining characters: a letter followed by a combining accent is two code points, so even a character count may differ from what a user perceives as one symbol. Grapheme-aware functions exist for that case.
  • Numeric values: in coercive mode strlen(100) measures the text "100". Relying on this makes code harder to read.

Common mistakes

  1. Treating the result as a character count. Validating a name field with strlen() can reject or accept the wrong input when users type accented letters or non-Latin scripts.
  2. Passing an array. Use count() for arrays. strlen() is for strings only.
  3. Measuring before trimming. A value consisting only of spaces has a positive length, so it passes a naive non-empty check.
  4. Forgetting about null. Values from optional input may be null. Normalize them to a string, or check for null explicitly, before measuring.
  5. Assuming a limit on display width. Byte length says nothing about how wide text appears on screen.
  • mb_strlen() counts characters in a given encoding.
  • grapheme_strlen() counts grapheme units.
  • iconv_strlen() returns the character count using iconv.
  • count() counts array elements or Countable objects.

Recap

strlen(string $string): int returns the number of bytes in a string. It is fast and reliable for ASCII text, binary data and byte limits. It does not count characters in multibyte text. Pass real strings, remember that strict typing rejects other scalar types, and choose a multibyte or grapheme function when the human-visible length matters.

Tested examples

Basic lengths including spaces and an empty string
<?php
$values = ['abcdef', ' ab cd ', ''];
foreach ($values as $value) {
    echo strlen($value), PHP_EOL;
}
Output
6
7
0
Bytes versus characters in UTF-8
<?php
$samples = [
    'ascii' => 'PHP',
    'accented' => "caf\u{00E9}",
    'euro' => "\u{20AC}",
    'emoji' => "\u{1F600}",
];
$lengths = [];
foreach ($samples as $name => $text) {
    $lengths[$name] = strlen($text);
}
echo json_encode($lengths), PHP_EOL;
Output
{"ascii":3,"accented":5,"euro":3,"emoji":4}
Binary data and strict types
<?php
declare(strict_types=1);

$binary = "a\0b";
$number = 12345;

echo json_encode([
    'binary' => strlen($binary),
    'number_as_text' => strlen((string) $number),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;

try {
    echo strlen($number);
} catch (TypeError $e) {
    echo get_class($e), PHP_EOL;
}
Output
{"binary":3,"number_as_text":5}
TypeError