Regex for an IPv4 address
Use ^(?:(?: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)$. Each octet is spelled out as 250-255, 200-249, 100-199, or 0-99, so 256 and 999 fail. Leading zeros such as 01 are rejected.
JavaScript ✓PCRE ✓
No catastrophic-backtracking patterns found. (A heuristic check: nested and adjacent repeats, overlapping alternatives.)
^Start of the stringanchor(?:…)Non-capturing group: groups without rememberinggroup(?:…)Non-capturing group: groups without rememberinggroup|Either of 4 alternatives, tried left to right; the first that leads to an overall match winsalternation- Alternative 1:
25The text "25" literallyliteral[0-5]One character: '0' to '5'character class- Alternative 2:
2The character '2' literallyliteral[0-4]One character: '0' to '4'character class\dA digit (0-9)character type- Alternative 3:
1The character '1' literallyliteral\dA digit (0-9)character type\dA digit (0-9)character type- Alternative 4:
[1-9]One character: '1' to '9'character class?Repeat the class optionally (zero or one time)quantifier\dA digit (0-9)character type\.The character '.' literallyliteral{3}Then repeat the whole group exactly 3 timesquantifier(?:…)Non-capturing group: groups without rememberinggroup|Either of 4 alternatives, tried left to right; the first that leads to an overall match winsalternation- Alternative 1:
25The text "25" literallyliteral[0-5]One character: '0' to '5'character class- Alternative 2:
2The character '2' literallyliteral[0-4]One character: '0' to '4'character class\dA digit (0-9)character type- Alternative 3:
1The character '1' literallyliteral\dA digit (0-9)character type\dA digit (0-9)character type- Alternative 4:
[1-9]One character: '1' to '9'character class?Repeat the class optionally (zero or one time)quantifier\dA digit (0-9)character type$End of the stringanchor
Examples
Checked at build time in JavaScript and in Python's re.
| Input | Matches? |
|---|---|
192.168.1.1 | ✓ match |
255.255.255.255 | ✓ match |
0.0.0.0 | ✓ match |
256.1.1.1 | ✗ no match |
01.2.3.4 | ✗ no match |
1.2.3 | ✗ no match |
1.2.3.4.5 | ✗ no match |
192.168.1.1/24 | ✗ no match |
10.0.0.1 | ✗ no match |
999.999.999.999 | ✗ no match |
Try your own text
One string per line: each line is tested on its own (the m flag is added here).
How it works
A regex cannot compare numbers, so the range 0-255 has to be written as text ranges. 25[0-5] covers 250-255, 2[0-4]\d covers 200-249, 1\d\d covers 100-199, and [1-9]?\d covers 0-99 without a leading zero. The first group repeats three times with a dot; the last octet has no dot after it.
Rejecting leading zeros is deliberate. Some parsers, including the C library's inet_aton, read 010 as octal 8, so 010.0.0.1 can mean 8.0.0.1 to one program and 10.0.0.1 to another. That mismatch has caused real access-control bypasses. Python's ipaddress module has rejected leading zeros since 3.9.5 for the same reason.
Variants
/\b(?:(?: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)\b/gFind addresses inside a log line. Word boundaries replace the anchors./^(?:\d{1,3}\.){3}\d{1,3}$/Shape only. Accepts out-of-range octets like 999.
Gotchas
- The common shortcut
^(\d{1,3}\.){3}\d{1,3}$accepts999.999.999.999. Fine for finding addresses in logs; wrong for validation. inet_atonand many browsers accept short forms like127.1(meaning 127.0.0.1) and hex like0x7f.0.0.1. This regex rejects them, which is usually what you want, but be aware that other software on the path may not.- CIDR notation like
10.0.0.0/8fails because of the$. See CIDR ranges for that format. - In Node,
require("net").isIP(s)returns 4, 6 or 0 and also rejects leading zeros. It is simpler than maintaining the regex.
Related explainers
- Regex for an http or https URLA regex that checks a string is an http or https URL, where it falls short, and why new URL() is the...
- Regex for digits only, integers and decimalsRegexes for digits only, signed integers and decimal numbers, with the edge cases: leading zeros, a bare...
- Regex for a US ZIP codeA regex for 5-digit US ZIP codes and ZIP+4, why ZIP codes must be stored as strings, and what a format...