33

Please suggest a single JS regex that can validate:

  • IPv4 address
  • IPv6 address

This regex should only validate address & no hostnames.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Mayank
  • 399
  • 1
  • 3
  • 6
  • For those who are working on a node environment like me, the `net` has a method called `isIP` that matches both IPv4 and IPv6. https://nodejs.org/api/net.html#netisipinput – Chubby Cows Jan 09 '23 at 17:22

3 Answers3

24

I had the exact same necessity, so I adapted the regex from Daniel's great answer (which is the most accurate I was able to find) to NOT validate hostnames. Here it is:

var expression = /((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((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})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((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})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((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}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((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}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((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}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((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}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((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}))|:)))(%.+)?\s*$))/;

if (expression.test(valueToTest))
{
    // good IP
}
else
{
    // bad IP
}

I forked Daniel's original JSFiddle to use this modified version cause I liked the extensive list of examples he provides. You can find the modified JSFiddle here, which should match your needs.

Hope this helps as much as it has helped me! :)

Community
  • 1
  • 1
GigiSan
  • 1,170
  • 2
  • 19
  • 30
  • 1
    Forgive me for resuming this old question but none of the above worked for me, cause Pedro Lobito's answer [validates "house" as a valid IP](https://jsfiddle.net/hnyagmdm/) and also I was looking for a single expression for both IPv4 and IPv6. – GigiSan Dec 30 '15 at 11:52
  • A few errors in the tests : "::2:3:4:5:6:7:8" should not be a valid IPv6. "::" cannot be used for one "0" segment. it should have been "0:2:3:4:5:6:7:8" due to the limit of 8 quartet per ipv6, not 9. Same for "::0:0:0:0:0:0:0", "::0:a:b:c:d:e:f", ":::2222:3333:4444:5555:6666:7777:8888", "::2222:3333:4444:5555:6666:7777:8888" – Remy Burney Jul 27 '21 at 02:35
  • More Errors in the tests : "::2222:3333:4444:5555:6666:123.123.123.123" is not valid because the ipv4 at the end represents 4bytes, so 2 quartet, marking a total of 9quartets instead of 8, so it's invalid. "1111:2222:3333:4444:5555:6666:000.000.000.000" is valid, if you consider the ipv4 "000.000.000.000" as valid, same for "1111:2222:3333:4444:5555:6666:00.00.00.00" – Remy Burney Jul 27 '21 at 02:35
8

The most up to date and correct regex I could find is inside an npm package: ip-regex.

After doing some modifications for vanillas JavaScript and tests it works accordingly and you can use it like this:

IPv4 Regex:

let ipv4_regex = /^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/gm;   
      
console.log(ipv4_regex.test('1.1.1.1'));
console.log(ipv4_regex.test('.100.100.100.100'));
console.log(ipv4_regex.test('256.100.100.100.100'));

IPv6 Regex:

let ipv6_regex = /^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/gm;     
          
console.log(ipv6_regex.test('2606:4700:4700::64'));
console.log(ipv6_regex.test('::1111:2222:3333:4444:5555:6666::'));
console.log(ipv6_regex.test('1:2:3::4:5::7:8'));

IPv4 + IPv6 Combined Regex:

let ipv46_regex = /(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$)/gm;      
      
console.log(ipv46_regex.test('1.1.1.1'));
console.log(ipv46_regex.test('.100.100.100.100'));
console.log(ipv46_regex.test('256.100.100.100.100'));
console.log(ipv46_regex.test('2606:4700:4700::64'));
console.log(ipv46_regex.test('::1111:2222:3333:4444:5555:6666::'));
console.log(ipv46_regex.test('1:2:3::4:5::7:8'));

Enjoy.

Mecanik
  • 1,539
  • 1
  • 20
  • 50
2

I compiled these regex formulas once I could not find, in my opinion, a better solution that worked well for both IPv4 and IPv6. It does include capture groups per my own requirements but it should have no effect on it working or not.

IPv4 Regex:

^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$

IPv6 Regex:

^((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4}))*::((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4}))*|((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4})){7}$

Implementation Example:

IPv4: if ( /^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$/g.test(ipv4)) {}
IPv6: if ( /^((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4}))*::((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4}))*|((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4})){7}$/g.test(ipv6)) {}

I'm sort of an amature with Regex so feedback on my attempt would be appreciated.

  • please not that your ipv6 Regex is not complacently valid. values such as these would not work. (please ignore the subnet notation ) https://en.wikipedia.org/wiki/IPv6_address#Default_address_selection this means that the address 1:: and address ::1 would not work in your example – user3813249 Jun 14 '16 at 23:40
  • also not that string such as this are also valid 1:4:1:2:2:2::2:2:2:1:1:21:1 for your ipv6 regedit – user3813249 Jun 14 '16 at 23:48
  • When I first developed these formulas I had very little knowledge of valid IPv6 addresses. In fact, I'm still a tiny bit hazy on them. Like I said, I'm not a pro at regex, but when I had trouble finding answers elsewhere, I was able to formulate these and they satisfied my requirements. – Ms. Amelia S. Greene Jun 16 '16 at 01:16
  • The IPv4 Regex does not work at all, and the IPv6 Regex is faulty. After 7 years I think it would be best to update this answer correctly... since this post is very indexed. – Mecanik Oct 23 '21 at 05:14
  • your ipv6 RegExp doesn't support addresses that include ipv4 component `2001:db8:3333:4444:5555:6666:1.2.3.4` – Sh eldeeb Nov 04 '22 at 02:11