text = "Hello, World!"
print("World" in text)
print("Universe" in text)
That's it. That's how you check if a Python string contains a substring. The in operator. Two words. Returns a boolean. Done. If you came here from Google, you can probably stop reading now — but stick around because there are like 5 other ways to do this, and some of them are genuinely useful in specific situations.
The in Operator — Your Default Choice
The in operator is what you should reach for 90% of the time. It's readable, it's fast, and literally everyone on your team will understand it.
email = "[email protected]"
if "@" in email:
print("Looks like an email")
else:
print("Nope")
One thing to keep in mind — it's case-sensitive. "world" in "Hello, World!" returns False. We'll fix that later.
str.find() — When You Need the Position
Sometimes you don't just want to know if a substring exists — you want to know where it is. That's what .find() is for. It returns the index of the first occurrence, or -1 if it's not found.
text = "Python is awesome"
print(text.find("is"))
print(text.find("sucks"))
I see a lot of old code using .find() != -1 as a contains check. It works, but honestly... just use in. The -1 sentinel value is a relic from C. Python gave us something better.
str.index() — find() But Angrier
.index() does the exact same thing as .find(), except it throws a ValueError if the substring isn't found instead of returning -1.
text = "Python is awesome"
print(text.index("is"))
try:
print(text.index("sucks"))
except ValueError as e:
print(f"Error: {e}")
When would you use this over .find()? Basically when the substring should be there and its absence is a bug. The exception makes the failure loud instead of silently returning -1 and causing weird behavior three functions later.
str.count() — How Many Times?
Need to know not just if a string contains something, but how many times? That's .count().
text = "banana"
print(text.count("a"))
print(text.count("na"))
print(text.count("z"))
A return value of 0 means "not found," so you could technically use .count() > 0 as a contains check. But that's doing extra work — it scans the entire string counting occurrences when you only need to know if there's at least one. Use in for boolean checks.
Case-Insensitive Python String Contains
This is the one that trips people up. The in operator is case-sensitive, so you need to normalize both sides:
text = "Hello, World!"
query = "hello"
# Option 1: .lower() both sides
print(query.lower() in text.lower())
# Option 2: casefold (handles Unicode edge cases)
print(query.casefold() in text.casefold())
Use .casefold() if you're dealing with international text. For English-only strings, .lower() is fine. I've seen people import regex just for case-insensitive contains — please don't. This is simpler.
Regex — The Nuclear Option
Sometimes you need pattern matching, not just substring matching. That's where re.search() comes in.
import re
text = "Order #12345 shipped"
match = re.search(r"#\d+", text)
if match:
print(f"Found: {match.group()}")
Regex is powerful but it's also slower and harder to read. If you're just checking for a plain substring, regex is overkill. Save it for actual patterns — emails, phone numbers, order IDs, that kind of thing.
Python vs JavaScript — String Contains
Coming from JavaScript? You're probably used to .includes(). Here's how it maps:
// JavaScript
const text = "Hello, World!";
console.log(text.includes("World")); // true
console.log(text.indexOf("World")); // 7
console.log(text.indexOf("Universe")); // -1
And the Python equivalents:
# Python
text = "Hello, World!"
print("World" in text) # True (like .includes())
print(text.find("World")) # 7 (like .indexOf())
print(text.find("Universe")) # -1 (like .indexOf())
Honestly, I prefer Python's in syntax. It reads like English. JavaScript's .includes() is fine but "World" in text just looks cleaner to me. Fight me in the comments.
Quick Reference — Which Method to Use
in— "Does it contain this?" Boolean check. Use this by default..find()— "Where is it?" Returns index or -1..index()— "Where is it? (and crash if missing)" Returns index or raises ValueError..count()— "How many times?" Returns count.re.search()— "Does it match this pattern?" For complex patterns only.
That covers basically every way to check if a Python string contains a substring. The in operator handles 90% of cases. Use the others when you need position info, counts, or pattern matching.
Need to convert string handling code between Python and JavaScript? CodeConverter handles it automatically — just paste your code and pick a target language.