str.find()

Locate a substring: its first index, or -1 when absent — the non-raising sibling of str.index.

String methodPython 2.0+Live demo
Common call
"hello".find("l")
Returns
int index, or -1 when absent
Replaces
str.index raises ValueError instead of returning -1
Watch out
-1 is truthy — "if s.find(x):" is a classic bug
str.find(subsubThe substring to locate.type: str · required, startstartSlice start, supports negative indexing.type: int · default: 0=0, endendSlice end (exclusive), supports negative indexing.type: int · default: len(s)=len(s))
int

Demo

Live evaluation
Try:
Inputs
stringstrthe source
substrto locate
startintsearch from
Output
'hello world'.find('o')
4

find scans left to right and reports the FIRST match. A missing substring returns -1 — no exception. The optional start restricts where the search begins.

Parameters

NameTypeRequiredDescription
substryesThe substring to locate.
startintno (0)Slice start, supports negative indexing.
endintno (len(s))Slice end (exclusive), supports negative indexing.

Return value

intThe lowest index where sub is found, or -1 when it does not occur. Never raises for a missing substring.

Common patterns

Check-then-slice
Find a marker and slice relative to it.
i = s.find(":")
if i != -1:
    value = s[i + 1:]
Existence check — prefer "in"
When you only need yes/no, the in operator says it better.
if "@" in email:   # not: email.find("@") != -1
    ...
Search from the right
rfind reports the LAST occurrence.
ext = path[path.rfind(".") + 1:]

Examples

1. First occurrence
"hello".find("l")
Returns
2
2. Missing substring
"hello".find("z")
Returns
-1
3. Search from an index
"hello world".find("o", 5)
Returns
7
4. Empty sub matches at 0
"abc".find("")
Returns
0

Pitfalls

1. -1 is truthy
Testing find() directly as a boolean inverts the logic: 0 (found at start) is falsy, -1 (absent) is truthy.
Backwards
if "hello".find("h"):
    print("found")
nothing — index 0 is falsy
Fix
if "hello".find("h") != -1:
    print("found")
found
2. find vs index
Same search, different failure mode — pick by whether absence is an error.
Silent -1 travels
pos = s.find(marker)
value = s[pos:]  # pos may be -1!
slice from -1 = last char — silently wrong
Fail fast
pos = s.index(marker)  # raises if absent
value = s[pos:]
ValueError at the real problem site

When to use

Use it
  • You need the position, and absence is a normal case
  • Slicing around a found marker
Reach for something else
  • Existence only → "sub" in s
  • Absence is a bug → str.index (raises)
  • Last occurrence → str.rfind
  • Pattern matching → re.search

Notes

Complexity
O(n·m) worst case; tuned two-way search in practice
Return
int (or -1)
CPython impl
Objects/unicodeobject.c :: unicode_find
Memory
No allocation
Thread-safe
Yes — str is immutable

FAQ

Identical search; find returns -1 for a missing substring while index raises ValueError. Use index when absence means a bug.

History

2.0
Method available on the unified string type.