re.findall

The quickest way to pull every occurrence out of a text. Read the return type rule first: capturing groups change what you get back. Also available as Pattern.findall(string, pos, endpos).

re functionPython 3 (all)Live demo
Common call
re.findall(r'\d+', 'a1 b22 c333')
Returns
['1', '22', '333'] — or groups, if the pattern has any
Replaces
a loop of search() calls, advancing by hand
Watch out
1 group → list of that group; 2+ groups → list of tuples. Use (?:...) to group without capturing
re.findall(patternpattern — The regular expression, as a raw string.type: str | re.Pattern · required, stringstring — The text to scan, left to right.type: str · required, flagsflags — Flags such as re.IGNORECASE. Not allowed with a compiled pattern.type: re.RegexFlag | int · default: 0=0)
→ list[str] | list[tuple[str, ...]]

Demo

Live evaluation
All matches, left to right, never overlapping.
Try:
Inputs
patternstra regular expression
textstrtext to scan
Code
import re
re.findall('\\d+', 'Order 66 shipped 3 boxes, 120 kg')
Result
['66', '3', '120']

The type rule in action: no group gives the whole matches, one group gives just that group's text, two groups give tuples — and (?:...) groups without capturing, so it behaves like no group. An optional group that did not take part becomes '' (not None). Empty matches are included: \d* on 'a1b' yields ['', '1', '', ''] — an empty match before a, the 1, then empty matches before b and at the very end.

Parameters

NameTypeRequiredDescription
patternstr | re.PatternyesThe regular expression, as a raw string.
stringstryesThe text to scan, left to right.
flagsre.RegexFlag | intno (0)Flags such as re.IGNORECASE. Not allowed with a compiled pattern.

Return value

list[str] | list[tuple[str, ...]] — Whole matches (no groups), group 1 (one group), or tuples of all groups (two or more). Unmatched groups give empty strings.

Common patterns

Numbers as ints
findall gives strings; convert in a comprehension.
import re
numbers = [int(n) for n in re.findall(r'-?\d+', text)]
Key/value pairs into a dict
Two groups → tuples → dict() takes them directly.
import re
settings = dict(re.findall(r'(\w+)\s*=\s*(\S+)', config_text))
Count occurrences
len() of the list, or sum(1 for _ in finditer(...)) to avoid building it.
import re
word_count = len(re.findall(r'\b\w+\b', text))

Examples

1. All numbers
import re re.findall(r'\d+', 'a1 b22 c333')
Returns
['1', '22', '333']
2. One group: only its text
import re re.findall(r'(\w)\d+', 'a1 b22 c333')
Returns
['a', 'b', 'c']
3. Two groups: tuples
import re re.findall(r'(\w)(\d+)', 'a1 b22 c333')
Returns
[('a', '1'), ('b', '22'), ('c', '333')]
4. Unmatched group is empty
import re re.findall(r'(\w)(\d)?', 'a1 b')
Returns
[('a', '1'), ('b', '')]
5. Pairs straight into a dict
import re dict(re.findall(r'(\w+)=(\d+)', 'x=1, y=22'))
Returns
{'x': '1', 'y': '22'}
6. Empty matches are included
import re re.findall(r'x*', 'axb')
Returns
['', 'x', '', '']
7. Case-insensitive
import re re.findall(r'python', 'Python PYTHON python', re.I)
Returns
['Python', 'PYTHON', 'python']

Pitfalls

1. A group used only for alternation
The parentheses around the alternatives capture, so findall returns just that part. Make the group non-capturing.
(com|org)
import re
re.findall(r'\w+\.(com|org)', 'a.com b.org')
['com', 'org']
(?:com|org)
import re
re.findall(r'\w+\.(?:com|org)', 'a.com b.org')
['a.com', 'b.org']
2. Expecting overlapping matches
Scanning resumes after each match. A lookahead with a group finds overlapping occurrences.
r'aa'
import re
re.findall(r'aa', 'aaaa')
['aa', 'aa']
r'(?=(aa))'
import re
re.findall(r'(?=(aa))', 'aaaa')
['aa', 'aa', 'aa']
3. Needing positions from findall
findall throws the positions away. finditer yields Match objects with start() and end().
findall
import re
re.findall(r'\d+', 'a1 b22')
['1', '22']
finditer
import re
[(m.group(), m.span()) for m in re.finditer(r'\d+', 'a1 b22')]
[('1', (1, 2)), ('22', (4, 6))]

When to use

Use it
  • Extracting every occurrence as plain strings (or group tuples)
  • Quick counts and dict-building from key/value text
Reach for something else
  • Need positions or named groups → re.finditer
  • Huge text where you stop early → re.finditer (lazy) instead of a full list
  • Only the first occurrence → re.search

Notes

CPython impl
pattern_findall in Modules/_sre/_sre.c builds the list directly — no Match objects are created, which makes it faster than finditer when you only need the text
Empty matches
Since Python 3.7 a non-empty match may start right where the previous empty match was
Groups
The rule depends on the number of groups in the pattern (Pattern.groups), not on which ones matched

FAQ

Your pattern has two or more capturing groups, so each item is a tuple of the groups. With exactly one group you get a list of that group's strings. Replace grouping-only parentheses with (?:...).