How to validate IP address in Python?

PythonValidationNetworkingIp Address

Python Problem Overview


What's the best way to validate that an IP entered by the user is valid? It comes in as a string.

Python Solutions


Solution 1 - Python

Don't parse it. Just ask.

import socket

try:
    socket.inet_aton(addr)
    # legal
except socket.error:
    # Not legal

Solution 2 - Python

From Python 3.4 on, the best way to check if an IPv6 or IPv4 address is correct, is to use the Python Standard Library module ipaddress - IPv4/IPv6 manipulation library s.a. https://docs.python.org/3/library/ipaddress.html for complete documentation.

Example :

#!/usr/bin/env python

import ipaddress
import sys

try:
    ip = ipaddress.ip_address(sys.argv[1])
    print('%s is a correct IP%s address.' % (ip, ip.version))
except ValueError:
    print('address/netmask is invalid: %s' % sys.argv[1])
except:
    print('Usage : %s  ip' % sys.argv[0])

For other versions: Github, phihag / Philipp Hagemeister,"Python 3.3's ipaddress for older Python versions", https://github.com/phihag/ipaddress

The backport from phihag is available e.g. in Anaconda Python 2.7 & is included in Installer. s.a. https://docs.continuum.io/anaconda/pkg-docs

To install with pip:

pip install ipaddress

s.a.: ipaddress 1.0.17, "IPv4/IPv6 manipulation library", "Port of the 3.3+ ipaddress module", https://pypi.python.org/pypi/ipaddress/1.0.17

Solution 3 - Python

import socket

def is_valid_ipv4_address(address):
    try:
        socket.inet_pton(socket.AF_INET, address)
    except AttributeError:  # no inet_pton here, sorry
        try:
            socket.inet_aton(address)
        except socket.error:
            return False
        return address.count('.') == 3
    except socket.error:  # not a valid address
        return False

    return True

def is_valid_ipv6_address(address):
    try:
        socket.inet_pton(socket.AF_INET6, address)
    except socket.error:  # not a valid address
        return False
    return True

Solution 4 - Python

The IPy module (a module designed for dealing with IP addresses) will throw a ValueError exception for invalid addresses.

>>> from IPy import IP
>>> IP('127.0.0.1')
IP('127.0.0.1')
>>> IP('277.0.0.1')
Traceback (most recent call last):
 ...
ValueError: '277.0.0.1': single byte must be 0 <= byte < 256
>>> IP('foobar')
Traceback (most recent call last):
 ...
ValueError: invalid literal for long() with base 10: 'foobar'

However, like Dustin's answer, it will accept things like "4" and "192.168" since, as mentioned, these are valid representations of IP addresses.

If you're using Python 3.3 or later, it now includes the ipaddress module:

>>> import ipaddress
>>> ipaddress.ip_address('127.0.0.1')
IPv4Address('127.0.0.1')
>>> ipaddress.ip_address('277.0.0.1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.3/ipaddress.py", line 54, in ip_address
    address)
ValueError: '277.0.0.1' does not appear to be an IPv4 or IPv6 address
>>> ipaddress.ip_address('foobar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.3/ipaddress.py", line 54, in ip_address
    address)
ValueError: 'foobar' does not appear to be an IPv4 or IPv6 address

For Python 2, you can get the same functionality using ipaddress if you install python-ipaddress:

pip install ipaddress

This module is compatible with Python 2 and provides a very similar API to that of the ipaddress module included in the Python Standard Library since Python 3.3. More details here. In Python 2 you will need to explicitly convert the IP address string to unicode: ipaddress.ip_address(u'127.0.0.1').

Solution 5 - Python

def is_valid_ip(ip):
    """Validates IP addresses.
    """
    return is_valid_ipv4(ip) or is_valid_ipv6(ip)

IPv4:

def is_valid_ipv4(ip):
    """Validates IPv4 addresses.
    """
    pattern = re.compile(r"""
        ^
        (?:
          # Dotted variants:
          (?:
            # Decimal 1-255 (no leading 0's)
            [3-9]\d?|2(?:5[0-5]|[0-4]?\d)?|1\d{0,2}
          |
            0x0*[0-9a-f]{1,2}  # Hexadecimal 0x0 - 0xFF (possible leading 0's)
          |
            0+[1-3]?[0-7]{0,2} # Octal 0 - 0377 (possible leading 0's)
          )
          (?:                  # Repeat 0-3 times, separated by a dot
            \.
            (?:
              [3-9]\d?|2(?:5[0-5]|[0-4]?\d)?|1\d{0,2}
            |
              0x0*[0-9a-f]{1,2}
            |
              0+[1-3]?[0-7]{0,2}
            )
          ){0,3}
        |
          0x0*[0-9a-f]{1,8}    # Hexadecimal notation, 0x0 - 0xffffffff
        |
          0+[0-3]?[0-7]{0,10}  # Octal notation, 0 - 037777777777
        |
          # Decimal notation, 1-4294967295:
          429496729[0-5]|42949672[0-8]\d|4294967[01]\d\d|429496[0-6]\d{3}|
          42949[0-5]\d{4}|4294[0-8]\d{5}|429[0-3]\d{6}|42[0-8]\d{7}|
          4[01]\d{8}|[1-3]\d{0,9}|[4-9]\d{0,8}
        )
        $
    """, re.VERBOSE | re.IGNORECASE)
    return pattern.match(ip) is not None

IPv6:

def is_valid_ipv6(ip):
    """Validates IPv6 addresses.
    """
    pattern = re.compile(r"""
        ^
        \s*                         # Leading whitespace
        (?!.*::.*::)                # Only a single whildcard allowed
        (?:(?!:)|:(?=:))            # Colon iff it would be part of a wildcard
        (?:                         # Repeat 6 times:
            [0-9a-f]{0,4}           #   A group of at most four hexadecimal digits
            (?:(?<=::)|(?<!::):)    #   Colon unless preceeded by wildcard
        ){6}                        #
        (?:                         # Either
            [0-9a-f]{0,4}           #   Another group
            (?:(?<=::)|(?<!::):)    #   Colon unless preceeded by wildcard
            [0-9a-f]{0,4}           #   Last group
            (?: (?<=::)             #   Colon iff preceeded by exacly one colon
             |  (?<!:)              #
             |  (?<=:) (?<!::) :    #
             )                      # OR
         |                          #   A v4 address with NO leading zeros 
            (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]?\d)
            (?: \.
                (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]?\d)
            ){3}
        )
        \s*                         # Trailing whitespace
        $
    """, re.VERBOSE | re.IGNORECASE | re.DOTALL)
    return pattern.match(ip) is not None

The IPv6 version uses "(?:(?<=::)|(?<!::):)", which could be replaced with "(?(?<!::):)" on regex engines that support conditionals with look-arounds. (i.e. PCRE, .NET)

Edit:

  • Dropped the native variant.
  • Expanded the regex to comply with the RFC.
  • Added another regex for IPv6 addresses.

Edit2:

I found some links discussing how to parse IPv6 addresses with regex:

Edit3:

Finally managed to write a pattern that passes all tests, and that I am also happy with.

Solution 6 - Python

I hope it's simple and pythonic enough:

def is_valid_ip(ip):
    m = re.match(r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$", ip)
    return bool(m) and all(map(lambda n: 0 <= int(n) <= 255, m.groups()))

Solution 7 - Python

I think this would do it...

def validIP(address):
    parts = address.split(".")
    if len(parts) != 4:
        return False
    for item in parts:
        if not 0 <= int(item) <= 255:
            return False
    return True

Solution 8 - Python

Consider IPv4 address as "ip".

if re.match(r'^((\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])$', ip):  
    print "Valid IP"  
else:
    print "Invalid IP"

Solution 9 - Python

I have to give a great deal of credit to Markus Jarderot for his post - the majority of my post is inspired from his.

I found that Markus' answer still fails some of the IPv6 examples in the Perl script referenced by his answer.

Here is my regex that passes all of the examples in that Perl script:

r"""^
     \s* # Leading whitespace
     # Zero-width lookaheads to reject too many quartets
     (?:
        # 6 quartets, ending IPv4 address; no wildcards
        (?:[0-9a-f]{1,4}(?::(?!:))){6}
             (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)
        (?:\.(?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}
      |
        # 0-5 quartets, wildcard, ending IPv4 address
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,4}[0-9a-f]{1,4})?
        (?:::(?!:))
             (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)
        (?:\.(?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}
      |
        # 0-4 quartets, wildcard, 0-1 quartets, ending IPv4 address
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,3}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:[0-9a-f]{1,4}(?::(?!:)))?
             (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)
        (?:\.(?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}
      |
        # 0-3 quartets, wildcard, 0-2 quartets, ending IPv4 address
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,2}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:[0-9a-f]{1,4}(?::(?!:))){0,2}
             (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)
        (?:\.(?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}
      |
        # 0-2 quartets, wildcard, 0-3 quartets, ending IPv4 address
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,1}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:[0-9a-f]{1,4}(?::(?!:))){0,3}
             (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)
        (?:\.(?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}
      |
        # 0-1 quartets, wildcard, 0-4 quartets, ending IPv4 address
        (?:[0-9a-f]{1,4}){0,1}
        (?:::(?!:))
        (?:[0-9a-f]{1,4}(?::(?!:))){0,4}
             (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)
        (?:\.(?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}
      |
        # wildcard, 0-5 quartets, ending IPv4 address
        (?:::(?!:))
        (?:[0-9a-f]{1,4}(?::(?!:))){0,5}
             (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)
        (?:\.(?:25[0-4]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}
      |
        # 8 quartets; no wildcards
        (?:[0-9a-f]{1,4}(?::(?!:))){7}[0-9a-f]{1,4}
      |
        # 0-7 quartets, wildcard
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,6}[0-9a-f]{1,4})?
        (?:::(?!:))
      |
        # 0-6 quartets, wildcard, 0-1 quartets
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,5}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:[0-9a-f]{1,4})?
      |
        # 0-5 quartets, wildcard, 0-2 quartets
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,4}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,1}[0-9a-f]{1,4})?
      |
        # 0-4 quartets, wildcard, 0-3 quartets
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,3}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,2}[0-9a-f]{1,4})?
      |
        # 0-3 quartets, wildcard, 0-4 quartets
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,2}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,3}[0-9a-f]{1,4})?
      |
        # 0-2 quartets, wildcard, 0-5 quartets
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,1}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,4}[0-9a-f]{1,4})?
      |
        # 0-1 quartets, wildcard, 0-6 quartets
        (?:[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,5}[0-9a-f]{1,4})?
      |
        # wildcard, 0-7 quartets
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,6}[0-9a-f]{1,4})?
     )
     (?:/(?:1(?:2[0-7]|[01]\d)|\d\d?))? # With an optional CIDR routing prefix (0-128)
     \s* # Trailing whitespace
    $"""

I also put together a Python script to test all of those IPv6 examples; it's here on Pastebin because it was too large to post here.

You can run the script with test result and example arguments in the form of "[result]=[example]", so like:

python script.py Fail=::1.2.3.4: pass=::127.0.0.1 false=::: True=::1

or you can simply run all of the tests by specifying no arguments, so like:

python script.py

Anyway, I hope this helps somebody else!

Solution 10 - Python

I came up with this simple version

def ip_checkv4(ip):
    	parts=ip.split(".")
    	if len(parts)<4 or len(parts)>4:
    		return "invalid IP length should be 4 not greater or less than 4"
    	else:
    		while len(parts)== 4:
    			a=int(parts[0])
    			b=int(parts[1])
    			c=int(parts[2])
    			d=int(parts[3])
    			if a<= 0 or a == 127 :
    				return "invalid IP address"
    			elif d == 0:
    				return "host id  should not be 0 or less than zero " 
    			elif a>=255:
    				return "should not be 255 or greater than 255 or less than 0 A"
    			elif b>=255 or b<0:	
    				return "should not be 255 or greater than 255 or less than 0 B"
    			elif c>=255 or c<0:
    				return "should not be 255 or greater than 255 or less than 0 C"
    			elif d>=255 or c<0:
    				return "should not be 255 or greater than 255 or less than 0 D"
    			else:
    				return "Valid IP address ", ip
    	
    p=raw_input("Enter IP address")
    print ip_checkv4(p)

Solution 11 - Python

I only needed to parse IP v4 addresses. My solution based on Chills strategy follows:

def getIP():
valid = False
while not valid :
octets = raw_input( "Remote Machine IP Address:" ).strip().split(".")
try: valid=len( filter( lambda(item):0<=int(item)<256, octets) ) == 4
except: valid = False
return ".".join( octets )

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkrupanView Question on Stackoverflow
Solution 1 - PythonDustinView Answer on Stackoverflow
Solution 2 - PythonYohannView Answer on Stackoverflow
Solution 3 - PythontzotView Answer on Stackoverflow
Solution 4 - PythonSamat JainView Answer on Stackoverflow
Solution 5 - PythonMarkus JarderotView Answer on Stackoverflow
Solution 6 - PythonGrzegorz LuczywoView Answer on Stackoverflow
Solution 7 - Pythonchills42View Answer on Stackoverflow
Solution 8 - PythonRajeshView Answer on Stackoverflow
Solution 9 - PythonblagView Answer on Stackoverflow
Solution 10 - Pythondef_0101View Answer on Stackoverflow
Solution 11 - PythonhsarView Answer on Stackoverflow