Regex for IPv4 Address Validation
The naive \d{1,3}(\.\d{1,3}){3} accepts 999.999.999.999, so a correct IPv4 pattern has to spell out the 0–255 range as alternatives: 250–255, 200–249, 100–199, and 0–99. This pattern does that for each of the four octets and rejects leading zeros (01.2.3.4), which some parsers dangerously interpret as octal.
/^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}$/How it works, token by token
| Token | Meaning |
|---|---|
| 25[0-5] | 250 through 255 |
| 2[0-4]\d | 200 through 249 |
| 1\d\d | 100 through 199 |
| [1-9]?\d | 0 through 99, with no leading zero |
| (\.(…)){3} | a dot plus the same octet alternatives, exactly three more times |
What it matches
192.168.0.1255.255.255.2558.8.8.8256.1.1.1192.168.101.2.3.4Try it live
One candidate per line — the m flag makes the ^ and $ anchors apply to each line. Edit anything; it runs in your browser.
Variations
^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}\/(3[0-2]|[12]?\d)$CIDR notation: the address plus /0 through /32\b(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}\bunanchored with word boundaries — extract addresses from logs with the g flagLanguage notes
- Why reject leading zeros? inet_aton and some parsers read 010 as octal 8 — a classic SSRF filter bypass.
- When a parser is available (ipaddress in Python, net.ParseIP in Go), prefer it — you get range checks and normalization for free.
Frequently asked questions
Why is the naive \d{1,3} pattern wrong?
It matches any three digits per octet, so 999.999.999.999 passes. IPv4 octets top out at 255, and expressing 'a number from 0 to 255' in regex requires the explicit alternatives this pattern uses.
Does this match IPv6 too?
No — IPv6 is a completely different format (hex groups separated by colons). See the IPv6 pattern for that; and if you need to accept both, test against the two patterns separately.
Building something custom? The regex tester gives you live match highlighting for any pattern.