IP Address Regex
Octet-accurate IPv4 matching — 999.1.1.1 fails; leading-zero-tolerant and canonical variants with CI-verified rows and the live tester.
Pattern variants
Pragmatic
/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/
What it matches
Four dot-separated octets, each 0-255, with leading zeros tolerated (192.168.001.1).
What it deliberately doesn't
Octets above 255 (999.1.1.1 fails), CIDR suffixes, ports and IPv6.
Strict
/^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/
What it matches
Canonical dotted-quad form: four octets 0-255 with no leading zeros.
What it deliberately doesn't
Zero-padded octets — inet_aton-style parsers read 0177 as octal 127, so the canonical form refuses the ambiguity.
Verified vectors
| Input | Pragmatic | Strict | Note |
|---|---|---|---|
"203.0.113.42" | ✓ matches | ✓ matches | |
"192.168.1.1" | ✓ matches | ✓ matches | |
"255.255.255.255" | ✓ matches | ✓ matches | the top of every octet range |
"0.0.0.0" | ✓ matches | ✓ matches | |
"999.1.1.1" | ✗ no match | ✗ no match | octet above 255 |
"256.100.50.25" | ✗ no match | ✗ no match | octet above 255 |
"192.168.001.1" | ✓ matches | ✗ no match | leading-zero octet — octal to some parsers |
"10.0.0.01" | ✓ matches | ✗ no match | leading zero in the last octet |
"01.02.03.04" | ✓ matches | ✗ no match | every octet zero-padded |
"1.2.3" | ✗ no match | ✗ no match | three octets |
"1.2.3.4.5" | ✗ no match | ✗ no match | five octets |
"192.168.1.1 " | ✗ no match | ✗ no match | trailing space — anchors reject it |
Usage by language
JavaScript
Machine-verified/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/
/^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/
Python
Machine-verifiedre.compile(r"^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$")
re.compile(r"^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$")
Java
Syntax-reviewed — not machine-verifiedPattern.compile("^(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$")
Pattern.compile("^(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$")
Go
Syntax-reviewed — not machine-verifiedregexp.MustCompile(`^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$`)
regexp.MustCompile(`^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$`)
C#
Syntax-reviewed — not machine-verifiednew Regex(@"^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$")
new Regex(@"^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$")
PHP
Syntax-reviewed — not machine-verified'/^(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$/'
'/^(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$/'
Caveats
- Leading-zero octets are ambiguous: inet_aton-style parsers read 0177 as octal 127 — the strict variant refuses them.
- This validates one whole field; it does not check that the address is routable or public.
Related patterns
Do it offline:$ grep -E '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' hosts.txt
How to use it
- Take the pragmatic variant to fish addresses out of configs and logs, where zero-padded octets like 192.168.001.1 are common and harmless.
- Use strict where the string gets parsed again downstream — inet_aton-family parsers read a leading zero as octal, turning 0177 into 127.
- Probe the boundary rows in the preloaded tester: 255.255.255.255 holds while 256.100.50.25 collapses at its first octet.
Matching an IPv4 address takes more than digits and dots, because \d{1,3} happily accepts 999. This pattern spells each octet as an alternation — 25[0-5] for the top range, 2[0-4]\d for the two hundreds, [01]?\d\d? for everything below — so every field stops at 255. A strict variant additionally refuses leading zeros; twelve CI-verified vectors prove both on this page.
Examples
^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$pattern /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/
203.0.113.42 ✓ matches
255.255.255.255 ✓ matches
999.1.1.1 ✗ no match
1.2.3.4.5 ✗ no matchThe alternation earns its keep on row three: 999 fits three digits but no octet branch. Row four fails on count — four octets, never five.
^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$pragmatic /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/
strict /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/
192.168.001.1 pragmatic ✓ matches strict ✗ no match
10.0.0.01 pragmatic ✓ matches strict ✗ no match
192.168.1.1 pragmatic ✓ matches strict ✓ matchesZero-padding splits the variants: pragmatic tolerates what people type, strict refuses it because a downstream octal read makes 001 ambiguous.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
Shape says nothing about routability
A match confirms four in-range octets — not that the address is public, reachable or yours. Loopback, RFC 1918 and multicast all pass identically; classification is numeric work for the subnet calculator, not a pattern.
Common errors
Invalid regular expression: /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/: \ at end of pattern- Escaping every dot then deleting the last one strands a lone backslash at the end, which V8 refuses as a dangling escape. Remove the orphan or re-copy the line — every \. needs its dot.
FAQ
Why not just use \d{1,3} four times with dots?
Because it validates counts, not values — 999.999.999.999 sails through. The alternation here encodes 0-255 into the grammar itself, which is exactly the part people get wrong by hand.
Which variant belongs in a config linter?
Strict: machines disagree about leading zeros, and refusing 010.0.0.1 up front is cheaper than debugging an octal surprise later. Pragmatic suits grepping logs that other systems already wrote.
Does this pattern cover CIDR notation or IPv6?
Deliberately not — a /24 suffix or a colon-grouped address dies at the anchors, keeping each notation on its own page. The IPv6 sibling handles hex groups and :: compression.