re.fullmatch
Both ends anchored: the pattern has to account for every character. Cleaner and stricter than wrapping a pattern in ^…$ — $ lets a trailing newline slip through. Also available as Pattern.fullmatch(string, pos, endpos).
Demo
import re re.fullmatch('\\d{5}(-\\d{4})?', '90210-1234')
fullmatch backtracks until the match covers everything: .+? is lazy, yet fullmatch still returns all of 'abc', and with cat|category it moves on to the second alternative after 'cat' leaves text over. In the $ tab, \d+$ matches '42\n' in search and match because $ also matches just before a final newline; fullmatch rejects it.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| pattern | str | re.Pattern | yes | The regular expression, as a raw string. |
| string | str | yes | The value to validate; all of it must match. |
| flags | re.RegexFlag | int | no (0) | Flags such as re.IGNORECASE. Not allowed with a compiled pattern. |
Return value
re.Match | None — A match covering the entire string (from pos to endpos for Pattern.fullmatch), or None.
Common patterns
import re USERNAME = re.compile(r'[a-z][a-z0-9_]{2,15}') def valid_username(name): return USERNAME.fullmatch(name) is not None
import re if m := re.fullmatch(r'(\d{1,2}):(\d{2})', value): hours, minutes = int(m[1]), int(m[2])
Examples
Pitfalls
import re bool(re.match(r'^\d+$', '42\n'))
import re bool(re.fullmatch(r'\d+', '42\n'))
import re bool(re.match(r'^cat|dog$', 'catalog'))
import re bool(re.fullmatch(r'cat|dog', 'catalog'))
When to use
- Validating a complete value: IDs, codes, numbers, usernames
- Parsing a string that has exactly one expected shape
- Looking for the pattern inside longer text → re.search
- Checking just a prefix → re.match
- Numbers you will convert anyway → try int(value) / float(value)
Notes
FAQ
re.fullmatch(pattern, s) — it returns a Match only if the entire string matches. For example re.fullmatch(r'\d{5}', '90210') matches but '90210x' does not.