Pattern library / Validation
IPv4 Address Regex (Octets Limited to 0–255)
The lazy \d{1,3}(\.\d{1,3}){3} happily accepts 999.999.999.999. A usable IPv4 pattern clamps every octet to 0–255 — a longer expression, but the difference between validating and just counting dots.
^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$
Load this pattern into the tester →
How the pattern works
- Each octet alternation tries the safest shapes first:
25[0-5](250–255),2[0-4][0-9](200–249),1[0-9]{2}(100–199),[1-9]?[0-9](0–99). - Leading zeros (
192.168.001.1) are rejected — they are ambiguous (octal?) and banned by modern canonical form. Allow them with[0-9]{1,3}if legacy data needs it. - IPv4-mapped and CIDR notations (
10.0.0.0/8) are not covered — match the address part, then handle the suffix separately. - IPv6 is a different animal (hex groups and
::compression) — no compact, fully-correct IPv6 regex exists; parse it in code.
Test it: match & no-match examples
Every row is loaded straight into the tester — click Try to see the match live:
| Input | Result | Why | |
|---|---|---|---|
192.168.1.1 | Match | private range, valid | Try → |
255.255.255.255 | Match | broadcast, max octets | Try → |
0.0.0.0 | Match | all zeros valid | Try → |
256.1.1.1 | No match | octet over 255 | Try → |
192.168.1 | No match | only 3 groups | Try → |
192.168.01.1 | No match | leading zero rejected (strict) | Try → |
Where to use it
JavaScript
const IP = /^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$/;
IP.test('192.168.1.1'); // true
Python
import re
IP = r'^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$'
bool(re.fullmatch(IP, '10.0.0.255'))
Bash (log filtering)
grep -E '\b((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\b' access.log
Common mistakes
- Do not use \d{1,3} — 999.999.999.999 matches it.
- In grep/ERE the backslashes before dots are mandatory: unescaped . matches any character.
- Need to allow leading zeros for old logs? Swap each octet group for [0-9]{1,3} and accept the weaker validation.
FAQ
Why is my IP regex so long?
Because octets must stop at 255. Any pattern shorter than these four alternations per octet is accepting invalid addresses like 300.1.1.1.
Does this match private IPs like 192.168.x.x?
Yes — it validates structure, not ownership. Range classification (private/public/reserved) is a separate step done in code.
How do I extract IPs from a log line?
Drop the anchors and add word boundaries: \b((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\b — copy it straight into the tester.
Related patterns
URL Regex — Match http/https Links (Practical) · Log Level Regex — Match INFO / WARN / ERROR Lines · UUID Regex — Match Any UUID (1-5) Format
For GA4-specific patterns, see the GA4 regex cheat sheet, the page path regex guide, the event filter regex guide, the GA4 regex match types, the custom channel grouping guide and RE2 vs PCRE. Browse the full regex pattern library.