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.

PHP
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.

Python
"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() 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).
  • If you only need a yes/no answer, Python's in operator ("needle" in haystack) is the idiomatic choice, not find() — it reads clearly and sidesteps the sentinel-value issue entirely.
  • Python also has str.index(), which behaves like find() but raises ValueError instead of returning -1 when 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

PHP
strpos("hello world", "world"); // 6
Python
"hello world".find("world")  # 6
Both return the zero-based index of the first match.

Correctly checking "not found"

PHP
strpos("hello", "x") !== false; // false (not found)
Python
"hello".find("x") != -1  # False (not found)
PHP requires `!==` (strict) to avoid the `0`-is-falsy trap; Python's find() uses `-1` as its sentinel, which is less trap-prone but should still be compared explicitly rather than relied on as truthy/falsy.

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.