[python] How to validate IP address in Python?

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

This question is related to python validation networking ip-address

The answer is


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

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!


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').


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

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


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!


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

I came up with this noob 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)

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 )

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.


Don't parse it. Just ask.

import socket

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

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

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

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').


Don't parse it. Just ask.

import socket

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

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()))

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


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()))

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.


I came up with this noob 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)

Don't parse it. Just ask.

import socket

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

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

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.


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 )

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"

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').


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"

Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to validation

Rails 2.3.4 Persisting Model on Validation Failure Input type number "only numeric value" validation How can I manually set an Angular form field as invalid? Laravel Password & Password_Confirmation Validation Reactjs - Form input validation Get all validation errors from Angular 2 FormGroup Min / Max Validator in Angular 2 Final How to validate white spaces/empty spaces? [Angular 2] How to Validate on Max File Size in Laravel? WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for jquery

Examples related to networking

Access HTTP response as string in Go Communication between multiple docker-compose projects Can't access 127.0.0.1 How do I delete virtual interface in Linux? ConnectivityManager getNetworkInfo(int) deprecated Bridged networking not working in Virtualbox under Windows 10 Difference between PACKETS and FRAMES How to communicate between Docker containers via "hostname" java.net.ConnectException: failed to connect to /192.168.253.3 (port 2468): connect failed: ECONNREFUSED (Connection refused) wget: unable to resolve host address `http'

Examples related to ip-address

how to get the ipaddress of a virtual box running on local machine How to get ip address of a server on Centos 7 in bash How to extract IP Address in Spring MVC Controller get call? Can You Get A Users Local LAN IP Address Via JavaScript? Get the client IP address using PHP Express.js: how to get remote client address Identifying country by IP address Which terminal command to get just IP address and nothing else? How to find Port number of IP address? C# IPAddress from string