Free tech learning for everyone, from basics to pro

Python for NetworkingProgramming and Application SecurityBeginner

The Python ipaddress module: subnets, hosts and validation

In short: The ipaddress module is part of the standard library and understands IPv4 and IPv6. It validates addresses, works out network and broadcast addresses, splits blocks into subnets and checks membership. Use it instead of writing your own string handling for IP addresses.

Why not just use strings?

An IP address looks like text, but treating it as text leads to bugs. String comparison says "10.0.0.10" sorts before "10.0.0.9", and a home-made regular expression will happily accept 300.1.1.1. Python’s built-in ipaddress module understands addresses as numbers with rules, for both IPv4 and IPv6, and needs no installation.

The ipaddress moduleipaddressstandard libraryip_addressone host addressip_networka subnetip_interfaceaddress + masksubnets()split a blockhosts()usable addressesValidationcatch bad input
Figure 1. The ipaddress module gives you address, network and interface objects with useful methods.

Addresses, networks and interfaces

  • ip_address(): one address, such as a host or gateway.
  • ip_network(): a subnet, such as 192.168.10.0/24. By default it must be the network address; pass strict=False to accept a host address and mask.
  • ip_interface(): an address plus its mask, as configured on an interface.
import ipaddress

net = ipaddress.ip_network("192.168.10.0/24")
print(net.network_address, net.broadcast_address, net.netmask)
print(net.num_addresses - 2, "usable hosts")

intf = ipaddress.ip_interface("192.168.10.1/24")
print(intf.ip, intf.network)

addr = ipaddress.ip_address("192.168.10.50")
print(addr in net, addr.is_private)

v6 = ipaddress.ip_network("2001:db8:10::/64")
print(v6.num_addresses)

Subnetting and listing hosts

The subnets() method splits a block, either by a new prefix length or by how many bits to borrow. hosts() yields the usable addresses, skipping the network and broadcast addresses in IPv4. It is a generator, so it does not build a huge list unless you ask it to.

import ipaddress

block = ipaddress.ip_network("10.20.0.0/22")
for sub in block.subnets(new_prefix=24):
    hosts = list(sub.hosts())
    print(sub, "gateway", hosts[0], "last", hosts[-1])

print(list(ipaddress.ip_network("10.20.0.0/30").hosts()))

a = ipaddress.ip_network("10.20.0.0/24")
b = ipaddress.ip_network("10.20.0.128/25")
print(b.subnet_of(a), a.overlaps(b))

Tip: check your answers against the subnet calculator and the VLSM tool while you learn, then let Python do the bulk work.

Validating input safely

Validating user inputRead text"10.1.1.300"Parseip_address()ValueError?reject andexplainCheck rangeis_privateetc.Use itsafe tocontinue
Figure 2. Parse every address with ipaddress before using it, and handle ValueError cleanly.

Any address that comes from a person, a spreadsheet or an API should be parsed before you use it. Invalid input raises a ValueError, which you can catch and report clearly.

import ipaddress


def parse_host(text: str):
    try:
        return ipaddress.ip_address(text.strip())
    except ValueError:
        return None


for item in ["192.168.10.5", "10.1.1.300", "2001:db8::1", "server1"]:
    result = parse_host(item)
    print(item, "OK" if result else "invalid")

Validation is also a security control. If a script builds a command or a firewall rule from user input, checking the value with ipaddress stops odd strings from being passed through.

Practical uses at work

TaskUseful feature
Plan VLAN subnets from a site blocksubnets(new_prefix=...)
Check a new subnet does not clashoverlaps(), subnet_of()
Find which subnet a host is inaddr in net
Sort addresses correctlysorted(..., key=ipaddress.ip_address)
Summarise contiguous rangescollapse_addresses()

Common mistakes include forgetting strict=False when parsing "192.168.10.1/24" as a network, and calling list() on hosts() for a very large IPv6 network, which would never finish.

Practice

What happens with ip_network("192.168.10.1/24")?
It raises ValueError because host bits are set. Use strict=False, or ip_interface() if you want the address and its network.
How many /26 subnets does a /24 split into?
Four: borrowing two bits gives 2 to the power 2 subnets, each with 64 addresses.
Why sort addresses with key=ipaddress.ip_address rather than as strings?
String sorting compares character by character, so 10.0.0.10 comes before 10.0.0.9. Address objects sort by numeric value.

Key takeaways

  • ipaddress is built in and handles IPv4 and IPv6.
  • ip_address, ip_network and ip_interface model hosts, subnets and interface addresses.
  • subnets() splits blocks; hosts() yields usable addresses.
  • Parse every external address and catch ValueError.
  • Use overlaps() and subnet_of() to check address plans.
Tracks your learning on this device only. See your progress on the learning paths.

About the author

Mohamed Fayas

Founder of FM TecHub. CCNA certified, with a BTEC HND in Network Engineering, and BEng (Hons) in Computer Networking and Cloud Security. He writes practical, plain-English guides on networking, security and cloud.

More about the author

Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.

Stay up to date by email

New notes, tools and security news from FM TecHub, explained simply. Free.

We only use your email to send these updates. See our privacy policy.