Last modified: Nov 01, 2026
Python Startswith and Endswith
Checking the start or end of a string is a common task. You may validate file extensions, URLs, or log prefixes. Python provides two built-in methods for this. They are startswith() and endswith().
These methods are fast and easy to read. They return a boolean value. This guide explains the syntax and shows practical examples. It also covers tuples, start and end arguments, and common mistakes.
What Do startswith and endswith Do?
The startswith method checks if a string begins with a given prefix. The endswith method checks if it ends with a given suffix. Both return True or False.
They are case-sensitive by default. That means "Hello" and "hello" are different. You can normalize case when needed. We cover that later in this guide.
These methods are safer than slicing. Slicing can raise errors with wrong indices. The startswith and endswith methods handle lengths gracefully. They also express intent clearly.
Basic Syntax and Examples
Call the method on the string. Pass the prefix or suffix as the first argument. The result is a boolean.
text = "Python is great" print(text.startswith("Python")) # Check the prefix print(text.endswith("great")) # Check the suffix True True If the prefix or suffix does not match, the method returns False. No error is raised. This makes them safe for validation.
text = "report.pdf" print(text.endswith(".txt")) # Wrong extension False An empty string always returns True. That is because every string starts and ends with an empty string. Keep this in mind when validating user input.
Using Tuples for Multiple Checks
You can pass a tuple of options. The method returns True if any option matches. This avoids long chains of or conditions. It is cleaner and faster.
filename = "photo.jpg" images = (".jpg", ".png", ".gif") print(filename.endswith(images)) # Check several suffixes True Tuples work with startswith too. Use them for protocol checks. For example, check if a URL starts with http or https.
url = "https://example.com" print(url.startswith(("http://", "https://"))) True Always pass a tuple, not a list, for multiple options. Lists are not accepted and raise a TypeError. Tuples are the correct type here.
Using Start and End Arguments
Both methods accept optional start and end arguments. They limit the search to a slice of the string. This is useful for parsing fixed-width data.
text = "xxHelloxx" print(text.startswith("Hello", 2)) # Start checking at index 2 print(text.endswith("Hello", 0, 7)) # Check within a range True True The start argument is inclusive. The end argument is exclusive. This matches the slicing rules. If you know string slicing, the behavior is familiar. For a refresher, see this guide on Python string slicing explained.
These arguments help when you only want to check part of a string. For example, skip a known prefix before checking. This avoids false matches in the middle of the text.
Case-Insensitive Checks
The methods are case-sensitive. "Report.PDF" does not end with ".pdf". Normalize the string before checking. Use lower or casefold to avoid mismatches.
filename = "Report.PDF" print(filename.lower().endswith(".pdf")) # Normalize case first True For Unicode text, casefold is more reliable than lower. This guide on Python upper and lower case strings explains the difference. Use casefold when comparing international text.
Normalize both sides if needed. For example, lower the string and the suffix. This prevents subtle bugs in validation code.
Practical Examples
File extension checks are a classic use case. You can validate uploads or filter files. Tuples make this easy and readable.
files = ["a.txt", "b.jpg", "c.pdf"] for f in files: if f.endswith((".txt", ".pdf")): print(f, "is a document") a.txt is a document c.pdf is a document URL validation is another common task. Check the scheme before processing. Use startswith with a tuple of schemes. This keeps the check short.
links = ["https://a.com", "ftp://b.com"] for link in links: if link.startswith(("http://", "https://")): print(link, "is a web link") https://a.com is a web link Log parsing often uses prefixes. For example, error logs may start with "ERROR". Filter them with startswith. This is fast and clear.
If you need to check for a general substring, these methods are not enough. Use the in operator instead. This guide on checking if a string contains a substring covers that approach.
Common Mistakes and How to Fix Them
One common mistake is passing a list instead of a tuple. Python raises a TypeError. Always use parentheses for multiple options.
Another mistake is forgetting case sensitivity. Users often expect ".PDF" and ".pdf" to match. Normalize the string first. Then call the method.
Also watch for whitespace. User input may have trailing spaces. Use the strip() method before checking. This removes unwanted spaces and newlines.
Do not confuse startswith with a substring search. It only checks the beginning. A match in the middle returns False. Use the in operator for general searches.
Finally, remember that empty strings match everything. Guard against empty input if that matters. Add a length check before the method call.
Performance and Best Practices
These methods are fast. They scan only as far as needed. For startswith, they stop at the first mismatch. That makes them efficient for long strings.
Tuples are faster than chained or conditions. They also read better. Use tuples for a fixed set of options. Avoid building dynamic tuples in hot loops.
Keep checks close to where they are used. Avoid storing booleans in unclear variables. A direct call inside an if statement is often clearest.
Name your prefixes and suffixes clearly. For example, IMAGE_EXTENSIONS is better than a magic tuple. This improves maintenance.
When printing results, format them neatly. Compare Python string formatting methods to choose the best style. Clear output helps with debugging and logs.
Conclusion
Python startswith and endswith are simple but powerful. Use them to check prefixes and suffixes. Pass tuples for multiple options. Use start and end arguments to limit the search. Normalize case when needed. Avoid lists and empty input pitfalls. With these tips, your string validation code will be clean, fast, and reliable.