stripos()
The stripos() function in PHP is used to find the position of the first occurrence of a substring in a string case-insensitively. It returns the position of the
Introduction
stripos() finds the position of the first occurrence of a substring inside a string, ignoring letter case. It returns the zero-based index where the match begins, or false when the substring is not present.
The i in the name stands for case-insensitive: "PHP", "php", and "Php" all match the same way. If you need a case-sensitive search instead, use strpos(). This page covers the syntax, the critical !== false gotcha, the optional $offset parameter, and how stripos() relates to the other position functions.
Syntax
stripos(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 index in $haystack where the search starts. Defaults to 0 (the beginning). A negative offset counts from the end of the string. |
Return value: the zero-based position of the first match (an int), or false if $needle is not found.
A basic example
The needle "fox" is lowercase but the haystack contains "FOX". Because stripos() ignores case, it still matches and prints:
Found 'fox' at position 16Switch to strpos() here and the result would be false, since the cases differ.
The !== false gotcha
This is the single most common bug with stripos() (and every *pos() function). When a match is found at the very start of the string, the return value is 0 — and 0 is falsy in PHP. A loose check like if (stripos(...)) would treat a real match as "not found":
<?php
$pos = stripos("Hello world", "hello");
// Wrong: 0 is falsy, so this branch runs even though there IS a match
if ($pos) {
echo "loose check: found\n";
} else {
echo "loose check: NOT found (wrong!)\n";
}
// Correct: compare against false with the strict !== operator
if ($pos !== false) {
echo "strict check: found at position $pos\n";
} else {
echo "strict check: not found\n";
}Output:
loose check: NOT found (wrong!)
strict check: found at position 0Always compare the result with !== false when you only want to know whether the substring exists.
Using the $offset parameter
The third argument lets you start searching partway through the string — handy for finding the second (or later) occurrence:
<?php
$text = "PHP is great. PHP is everywhere.";
$first = stripos($text, "php"); // start at 0
$second = stripos($text, "php", $first + 1); // skip past the first match
echo "First occurrence: $first\n";
echo "Second occurrence: $second\n";Output:
First occurrence: 0
Second occurrence: 14A practical use: case-insensitive keyword filter
Because it ignores case, stripos() is a natural fit for "does this text mention X?" checks, such as flagging messages that contain a banned word regardless of how it's typed:
<?php
$message = "Get this AMAZING deal now!";
$banned = ["amazing", "free", "winner"];
foreach ($banned as $word) {
if (stripos($message, $word) !== false) {
echo "Blocked: contains '$word'\n";
break;
}
}Output:
Blocked: contains 'amazing'Related functions
| Function | Case | Searches from |
|---|---|---|
stripos() | Insensitive | Start → first match |
strpos() | Sensitive | Start → first match |
strripos() | Insensitive | End → last match |
stristr() | Insensitive | Returns the matched substring, not its position |
See also substr() to extract text once you have a position, and str_replace() for case-sensitive replacements.
Conclusion
stripos() returns the zero-based position of the first case-insensitive match of a substring, or false if there is none. Remember to test the result with !== false so a match at position 0 is not mistaken for "not found", use $offset to find later occurrences, and reach for strpos() when case matters.