str.startswith allows you to supply a tuple of strings to test for:

if link.lower().startswith(("js", "catalog", "script", "katalog")):

From the docs:

str.startswith(prefix[, start[, end]])

Return True if string starts with the prefix, otherwise return False. prefix can also be a tuple of prefixes to look for.

Below is a demonstration:

>>> "abcde".startswith(("xyz", "abc"))
True
>>> prefixes = ["xyz", "abc"]
>>> "abcde".startswith(tuple(prefixes)) # You must use a tuple though
True
>>>
Answer from user2555451 on Stack Overflow
๐ŸŒ
W3Schools
w3schools.com โ€บ python โ€บ ref_string_startswith.asp
Python String startswith() Method
Python Examples Python Compiler ... Q&A Python Training ... The startswith() method returns True if the string starts with the specified value, otherwise False....
๐ŸŒ
Codecademy
codecademy.com โ€บ docs โ€บ python โ€บ strings โ€บ .startswith()
Python | Strings | .startswith() | Codecademy
April 17, 2025 - The .startswith() method in Python checks whether a string begins with a specified value and returns True if it does. Otherwise, it returns False.
Discussions

python - str.startswith with a list of strings to test for - Stack Overflow
I'm trying to avoid using so many comparisons and simply use a list, but not sure how to use it with str.startswith: More on stackoverflow.com
๐ŸŒ stackoverflow.com
Python: startswith any alpha character - Stack Overflow
How can I use the startswith function to match any alpha character [a-zA-Z]. For example I would like to do this: if line.startswith(ALPHA): Do Something More on stackoverflow.com
๐ŸŒ stackoverflow.com
Strange behavior when using String.startswith() with an empty string and a big start
When using 'test'.startswith(''), it came out as True, I was under the impression that startswith() was doing something like this: string[start:end] == value, but whenever start is equal or greater than the length of the string it results in False. So, I thought that values that would result ... More on discuss.python.org
๐ŸŒ discuss.python.org
3
0
September 29, 2021
python - How to use str.startswith with multiple strings? - Stack Overflow
I've tried using the or function to input multiple words for the same output, but it only takes the first word as the input and not the rest. How do I solve this? Thanks! For instance: message.cont... More on stackoverflow.com
๐ŸŒ stackoverflow.com
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ python โ€บ python-string-startswith
Python - String startswith() - GeeksforGeeks
April 29, 2025 - startswith() method in Python checks whether a given string starts with a specific prefix.
๐ŸŒ
YouTube
youtube.com โ€บ watch
How To Use Startswith Method In Python - YouTube
In this video we will learn How To Use Startswith Method In Python. The startswith method in python (startswith()), is a string method that can be used to ch...
Published: December 6, 2022
๐ŸŒ
Python Reference
python-reference.readthedocs.io โ€บ en โ€บ latest โ€บ docs โ€บ str โ€บ startswith.html
startswith โ€” Python Reference (The Right Way) 0.1 documentation
startswith ยท Edit on GitHub ยท Returns a Boolean stating whether a string starts with the specified prefix. str. startswith(prefix[, start[, end]]) prefix ยท Required. The substring looked for. prefix can also be a tuple of prefixes to look for. start ยท Optional.
Find elsewhere
๐ŸŒ
Python
docs.python.org โ€บ 3 โ€บ builtins โ€บ stdtypes.html
Built-in Types โ€” Python 3.14.7 documentation
>>> 'Python'.startswith('Py') True >>> 'a tuple of prefixes'.startswith(('at', 'a')) True >>> 'Python is amazing'.startswith('is', 7) True
๐ŸŒ
Programiz
programiz.com โ€บ python-programming โ€บ methods โ€บ string โ€บ startswith
Python String startswith()
text = "Python programming is easy." # start parameter: 7 # 'programming is easy.' string is searched ยท result = text.startswith('programming is', 7) print(result) # start: 7, end: 18 # 'programming' string is searched
๐ŸŒ
Python.org
discuss.python.org โ€บ python help
Strange behavior when using String.startswith() with an empty string and a big start - Python Help - Discussions on Python.org
September 29, 2021 - When using 'test'.startswith(''), it came out as True, I was under the impression that startswith() was doing something like this: string[start:end] == value, but whenever start is equal or greater than the length of the string it results in False. So, I thought that values that would result in out of bounds in other languages would all return False, but 'test'.startswith('', 0, 99), 'test'.startswith('', -99, 99) and 'test'.startswith('', -99, -99) return True.
๐ŸŒ
Pandas
pandas.pydata.org โ€บ docs โ€บ reference โ€บ api โ€บ pandas.Series.str.startswith.html
pandas.Series.str.startswith โ€” pandas 3.0.6 documentation
Equivalent to str.startswith(). ... Character sequence or tuple of strings. Regular expressions are not accepted. ... Object shown if element tested is not a string. The default depends on dtype of the array. For the "str" dtype, False is used. For object dtype, numpy.nan is used. For the nullable StringDtype, pandas.NA is used. ... A Series of booleans indicating whether the given pattern matches the start of each string element. ... Python standard library string method.
๐ŸŒ
Learn By Example
learnbyexample.org โ€บ python-string-startswith-method
Python String startswith() Method - Learn By Example
April 20, 2020 - Python ยท Determines whether the string starts with a given substring ยท The startswith() method returns True if the string starts with the specified prefix, otherwise returns False.
๐ŸŒ
Tutorialspoint
tutorialspoint.com โ€บ python โ€บ string_startswith.htm
Python String startswith() Method
The Python string method startswith() checks whether string starts with a given substring or not. This method accepts a prefix string that you want to search for and is invoked on a string object.
Top answer
1 of 10
33

I'd agree with the others that startswith is more readable, and you should use that. That said, if performance is a big issue for such a special case, benchmark it:

$ python -m timeit -s 'text="foo"' 'text.startswith("a")'
1000000 loops, best of 3: 0.537 usec per loop

$ python -m timeit -s 'text="foo"' 'text[0]=="a"'
1000000 loops, best of 3: 0.22 usec per loop

So text[0] is amost 2.5 times as fast - but it's a pretty quick operation; you'd save ~0.3 microseconds per compare depending on the system. Unless you're doing millions of comparisons in a time critical situation though, I'd still go with the more readable startswith.

2 of 10
33

text[0] fails if text is an empty string:

IronPython 2.6 Alpha (2.6.0.1) on .NET 4.0.20506.1
Type "help", "copyright", "credits" or "license" for more information.
>>> text = ""
>>> print(text.startswith("a"))
False
>>> print(text[0]=='a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: index out of range: 0

EDIT: You say you "know" that text is not empty... how confident are you of that, and what would you want to happen if it is empty in reality? If a failure is appropriate (e.g. it means a bug in your code) that would encourage the use of text[0]=='a'.

Other questions:

  • How concerned are you about the performance of this? If this is performance critical, then benchmark it on your particular Python runtime. I wouldn't be entirely surprised to find that (say) one form was faster on IronPython and a different one faster on CPython.

  • Which do you (and your team) find more readable?

๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ python โ€บ python-check-if-string-starts-with-any-element-in-list
Python - Check if string starts with any element in list - GeeksforGeeks
July 12, 2025 - startswith() method in Python can accept a tuple of strings to check if the string starts with any of them.
Top answer
1 of 3
34

There is technically no reason to accept other sequence types, no. The source code roughly does this:

if isinstance(prefix, tuple):
    for substring in prefix:
        if not isinstance(substring, str):
            raise TypeError(...)
        return tailmatch(...)
elif not isinstance(prefix, str):
    raise TypeError(...)
return tailmatch(...)

(where tailmatch(...) does the actual matching work).

So yes, any iterable would do for that for loop. But, all the other string test APIs (as well as isinstance() and issubclass()) that take multiple values also only accept tuples, and this tells you as a user of the API that it is safe to assume that the value won't be mutated. You can't mutate a tuple but the method could in theory mutate the list.

Also note that you usually test for a fixed number of prefixes or suffixes or classes (in the case of isinstance() and issubclass()); the implementation is not suited for a large number of elements. A tuple implies that you have a limited number of elements, while lists can be arbitrarily large.

Next, if any iterable or sequence type would be acceptable, then that would include strings; a single string is also a sequence. Should then a single string argument be treated as separate characters, or as a single prefix?

So in other words, it's a limitation to self-document that the sequence won't be mutated, is consistent with other APIs, it carries an implication of a limited number of items to test against, and removes ambiguity as to how a single string argument should be treated.

Note that this was brought up before on the Python Ideas list; see this thread; Guido van Rossum's main argument there is that you either special case for single strings or for only accepting a tuple. He picked the latter and doesn't see a need to change this.

2 of 3
22

This has already been suggested on Python-ideas a couple of years back see: str.startswith taking any iterator instead of just tuple and GvR had this to say:

The current behavior is intentional, and the ambiguity of strings themselves being iterables is the main reason. Since startswith() is almost always called with a literal or tuple of literals anyway, I see little need to extend the semantics.

In addition to that, there seemed to be no real motivation as to why to do this.

The current approach keeps things simple and fast, unicode_startswith (and endswith) check for a tuple argument and then for a string one. They then call tailmatch in the appropriate direction. This is, arguably, very easy to understand in its current state, even for strangers to C code.

Adding other cases will only lead to more bloated and complex code for little benefit while also requiring similar changes to any other parts of the unicode object.

๐ŸŒ
Reddit
reddit.com โ€บ r/python โ€บ python 'startswith' vs '==' performance
r/Python on Reddit: Python 'startswith' vs '==' performance
February 7, 2019 -

Noticed interesting thing: python startswith is 2 times slower then ==:

In [1]: k = "123123123"

In [2]: %timeit k[0] == "_"
50.1 ns ยฑ 1.83 ns per loop (mean ยฑ std. dev. of 7 runs, 10000000 loops each)

In [3]: %timeit k.startswith("_")
117 ns ยฑ 1.35 ns per loop (mean ยฑ std. dev. of 7 runs, 10000000 loops each)

Tested with python 3.5, 3.6, 2.7

I think it is because CALL_FUNCTION instruction:

In [25]: dis.dis('k.startswith("_")')
  1           0 LOAD_NAME                0 (k)
              3 LOAD_ATTR                1 (startswith)
              6 LOAD_CONST               0 ('_')
              9 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             12 RETURN_VALUE

and == executes only on stack:

In [26]: dis.dis('k[0] == "_"')
  1           0 LOAD_NAME                0 (k)
              3 LOAD_CONST               0 (0)
              6 BINARY_SUBSCR
              7 LOAD_CONST               1 ('_')
             10 COMPARE_OP               2 (==)
             13 RETURN_VALUE

(BINARY_SUBSCR is getitem instruction)

So be careful doing startswith, endswith and so on in huge cycles.
Also excellent article about python perfomance bottlenecks: https://gregoryszorc.com/blog/2019/01/10/what-i've-learned-about-optimizing-python/