PHP strpos() Equivalent in Python
Python's str.find() returns the same kind of index PHP's strpos() does, but the "not found" sentinel differs (-1 vs. false) in a way that's easy to get wrong with truthy checks.
Requires review Works only under specific conditions — read the caveats before relying on it.
- PHP source
strpos()- Closest Python API
str.find()- Idiomatic Python
in operator (for a boolean check)
Main limitation: PHP's `strpos()` returns `false` when the substring isn't found, and `0` when it's found at the very start — since `0 == false` in loose comparison, PHP code must use `!==` for a correct check; Python's `str.find()` returns `-1` for "not found", which is unambiguous in a boolean context (though still worth comparing explicitly).
How to use each function
Before comparing the two, here's how strpos() and str.find() work
on their own.
PHP: strpos()
strpos(string $haystack, string $needle, int $offset = 0): int|false
Finds the position of the first occurrence of a substring, searching from an optional starting offset. Returns false — not -1 — when the substring isn't found, so a match at position 0 must be checked with !== rather than a plain truthy check.
Returns: The zero-based integer offset of the first match, or false if not found.
strpos("hello world", "world"); // 6
strpos("hello world", "xyz"); // false Python: str.find()
str.find(sub, start=0, end=len(str))
Returns the lowest index of sub within the string, searching an optional start/end slice range. Returns -1 (never a boolean) when the substring is missing, which never collides with a real match position. str.index() behaves the same but raises ValueError instead of returning -1.
Returns: The zero-based integer index of the first match, or -1 if not found.
"hello world".find("world") # 6
"hello world".find("xyz") # -1 Quick mapping
| PHP | strpos() |
|---|---|
| Closest Python API | str.find() |
| Idiomatic Python | in operator (for a boolean check) |
How it differs
- PHP's
strpos()returnsfalsewhen the substring isn't found, and0when it's found at the very start — since0 == falsein loose comparison, PHP code must use!==for a correct check; Python'sstr.find()returns-1for "not found", which is unambiguous in a boolean context (though still worth comparing explicitly). - If you only need a yes/no answer, Python's
inoperator ("needle" in haystack) is the idiomatic choice, notfind()— it reads clearly and sidesteps the sentinel-value issue entirely. - Python also has
str.index(), which behaves likefind()but raisesValueErrorinstead of returning-1when the substring is missing — useful if a missing substring should be an error condition rather than a silently-handled case.
Examples
Finding a substring position
strpos("hello world", "world"); // 6 "hello world".find("world") # 6 Correctly checking "not found"
strpos("hello", "x") !== false; // false (not found) "hello".find("x") != -1 # False (not found) Edge cases
Edge case
The single most common bug when porting PHP's strpos() checks is testing if (strpos($haystack, $needle)) instead of if (strpos($haystack, $needle) !== false) — a match at position 0 is falsy in PHP. Python's str.find() != -1 doesn't have this specific trap, but don't assume if str.find(...) is safe either, since 0 is falsy in Python too.
References
- PHP Manual — strpos — checked 2026-07-29
- Python docs — str.find() (v3.x) — checked 2026-07-29
Last verified 2026-07-29.