strpos()
The strpos() function in PHP is used to find the position of the first occurrence of a substring in a string. It returns the numeric position of the first
Introduction
The strpos() function in PHP finds the position of the first occurrence of a substring inside another string. It returns the zero-based index of that occurrence, or the boolean false if the substring never appears. It is one of the most-used string functions in PHP — you reach for it whenever you need to ask "does this string contain that text, and where?".
This chapter covers the syntax, the all-important === false check, the $offset parameter, case-sensitivity, and the related functions you should know about.
Syntax
strpos(string $haystack, string $needle, int $offset = 0): int|false| Parameter | Description |
|---|---|
$haystack | The string to search in. |
$needle | The substring to search for. |
$offset | Optional. The character index at which to start searching. Defaults to 0 (the beginning). A negative offset counts from the end of the string. |
Return value: the integer position of the first match (counting from 0), or false when $needle is not found.
Basic example
"World" starts at index 6 in "Hello World" (the H is at index 0), so the output is:
Found 'World' in 'Hello World' at position 6The === false gotcha (read this)
This is the single most common strpos() bug. When the match is at the start of the string, strpos() returns 0 — and 0 is falsy in PHP. If you test the result with a loose check like if (!strpos(...)) or if (strpos(...) == false), a valid match at position 0 is mistaken for "not found".
<?php
$haystack = "php is great";
// WRONG: 0 is treated as "not found"
if (strpos($haystack, "php")) {
echo "loose: found\n";
} else {
echo "loose: not found (WRONG!)\n";
}
// RIGHT: use the strict !== operator
if (strpos($haystack, "php") !== false) {
echo "strict: found\n";
} else {
echo "strict: not found\n";
}Output:
loose: not found (WRONG!)
strict: foundAlways compare the result with the strict !== (or ===) operator. This is the golden rule of strpos().
Searching from an offset
The third argument tells strpos() where to begin. This is how you find the second (and later) occurrences of a substring — find the first one, then search again starting just past it.
<?php
$text = "cat, dog, cat, bird";
$first = strpos($text, "cat"); // 0
$second = strpos($text, "cat", $first + 1); // 10
echo "first: $first\n";
echo "second: $second\n";Output:
first: 0
second: 10A negative offset starts the search that many characters from the end of the string.
Case sensitivity
strpos() is case-sensitive: "World" and "world" are different needles.
<?php
var_dump(strpos("Hello World", "world")); // bool(false)
var_dump(strpos("Hello World", "World")); // int(6)If you need a case-insensitive search, use stripos() instead — it has the same signature but ignores letter case.
Just checking "does it contain X?"
If you only care whether a substring exists (not where), PHP 8.0+ offers the much clearer str_contains(), which returns a plain boolean and sidesteps the === false gotcha entirely:
<?php
// PHP 8.0+
var_dump(str_contains("Hello World", "World")); // bool(true)
var_dump(str_contains("Hello World", "world")); // bool(false)Use strpos() when you need the position; use str_contains() when you only need a yes/no answer.
Related functions
stripos()— case-insensitive version ofstrpos().strrpos()— finds the last occurrence instead of the first.strstr()— returns the part of the string from the first match onward.substr()— extract a slice once you know the position.str_replace()— replace all occurrences of a substring.preg_match()— pattern-based search when you need regular expressions.
Conclusion
strpos() returns the zero-based position of the first occurrence of a substring, or false if it is absent. Remember the two rules that trip people up most: always test the result with the strict !== false, and reach for stripos() or str_contains() when you need case-insensitive matching or a simple boolean check.