Tidy Desk Digital · Free guides

Checking IPv4 Subnet Membership in Python

Find which IPv4 addresses fall inside a network range. This local checker reports inside, outside and invalid lines without sending network traffic.

You'll need Python 3.10 or later, a plain-text editor and a command window. No extra packages are required.

1. Prepare the address list

An Internet Protocol version 4 (IPv4) address has four dot-separated numbers, such as 192.0.2.10. A subnet is a smaller address range within a network. A bit is a binary digit, either 0 or 1. A network written as 192.0.2.0/24 uses /24 to say that its first 24 bits describe the network. That range runs from 192.0.2.0 through 192.0.2.255.

Save this as addresses.txt in UTF-8, one address per line:

192.0.2.0
192.0.2.10
192.0.2.255
198.51.100.20
not-an-address

RFC 5737 is the published document that reserves these ranges for examples. The first and last addresses in the chosen range are included in membership testing. Whether an address can be assigned to a device is a separate question.

2. Write the checker

Save this as CheckSubnet.py beside the list:

import ipaddress as IpAddress
import sys as Sys
from pathlib import Path


def CheckSubnet(FileName, NetworkText):
    Network = IpAddress.IPv4Network(NetworkText, strict=True)
    with Path(FileName).open("rb") as Input:
        Data = Input.read(1048577)
    if len(Data) > 1048576:
        raise ValueError("input exceeds 1 MiB")
    Lines = Data.decode("utf-8-sig").splitlines()
    if len(Lines) > 1000:
        raise ValueError("more than 1000 input lines")
    Inside = 0
    Outside = 0
    Invalid = 0
    for Number, Line in enumerate(Lines, start=1):
        Text = Line.strip()
        try:
            Address = IpAddress.IPv4Address(Text)
        except ValueError:
            Invalid += 1
            print(f"Line {Number}: invalid IPv4 address")
            continue
        if Address in Network:
            Inside += 1
            print(f"Line {Number}: {Address} inside")
        else:
            Outside += 1
            print(f"Line {Number}: {Address} outside")
    print(f"Network: {Network}; inside: {Inside}; outside: {Outside}; invalid: {Invalid}")
    return 1 if Invalid else 0


def Main():
    if len(Sys.argv) != 3:
        print("Usage: python3 CheckSubnet.py addresses.txt NETWORK", file=Sys.stderr)
        return 2
    try:
        return CheckSubnet(Sys.argv[1], Sys.argv[2])
    except (OSError, UnicodeError, ValueError) as Error:
        print(f"Check stopped: {Error}", file=Sys.stderr)
        return 2


if __name__ == "__main__":
    raise SystemExit(Main())

IPv4Network checks the network you type. With strict=True, 192.0.2.1/24 stops because it has host bits set: the last eight bits describe a position inside this /24 range, and they are not all zero. The address part is not the start of that network. The program does not silently replace it with 192.0.2.0/24.

The file is read as UTF-8, with an optional byte-order mark at the beginning. The program reads at most 1 MiB (1,048,576 bytes, about one million), plus one extra byte to detect oversized input, and accepts at most 1,000 input lines. It removes surrounding whitespace from each address before checking it. Blank lines inside the file are invalid; a final newline does not create an extra address.

IPv4Address checks each line, then Address in Network tests membership. Invalid lines are counted without printing their original text. IPv6 addresses, such as 2001:db8::1, are rejected as invalid by this IPv4-only checker. Repeated addresses count each time they occur.

3. Run the check

Open a command window in the folder and run:

python3 CheckSubnet.py addresses.txt 192.0.2.0/24

If your installation uses python or py for Python 3, use that command instead. The output is:

Line 1: 192.0.2.0 inside
Line 2: 192.0.2.10 inside
Line 3: 192.0.2.255 inside
Line 4: 198.51.100.20 outside
Line 5: invalid IPv4 address
Network: 192.0.2.0/24; inside: 3; outside: 1; invalid: 1

An exit code is the small number returned when a program ends. This checker returns 0 when it finishes with no invalid addresses, 1 when it finishes with invalid lines, and 2 when the check stops, for example because the network is invalid or the file cannot be read. Outside addresses are normal results, not errors. An empty file prints zero totals.

4. Try a smaller network

Save this shorter list as small-addresses.txt, leaving your first example unchanged:

192.0.2.0
192.0.2.1
192.0.2.2

Run:

python3 CheckSubnet.py small-addresses.txt 192.0.2.0/31

A /31 range contains two addresses. The output is:

Line 1: 192.0.2.0 inside
Line 2: 192.0.2.1 inside
Line 3: 192.0.2.2 outside
Network: 192.0.2.0/31; inside: 2; outside: 1; invalid: 0

Now change only the network argument:

python3 CheckSubnet.py small-addresses.txt 192.0.2.1/32

A /32 contains one address, so the output becomes:

Line 1: 192.0.2.0 outside
Line 2: 192.0.2.1 inside
Line 3: 192.0.2.2 outside
Network: 192.0.2.1/32; inside: 1; outside: 2; invalid: 0

Both runs return exit code 0. An outside address is a valid result, not a failed check. Membership includes every address in the range; it is not the same operation as asking Python for a list of usable hosts.

Finally, try a device address where the checker expects a network address:

python3 CheckSubnet.py small-addresses.txt 192.0.2.1/24

The program returns exit code 2 and writes this error instead of membership results:

Check stopped: 192.0.2.1/24 has host bits set

It does not quietly change your argument to 192.0.2.0/24.

5. Keep the conclusion narrow

Inside means the address belongs to the mathematical range you supplied. It does not prove that a device exists, is reachable, belongs to you, is safe, or is allowed through a firewall, the rules controlling allowed network traffic. No ping, connection or lookup is made.

The program passed 16 command-line checks on Python 3.10.12, including network boundaries, /0, /31, /32, invalid addresses, host-bit errors and the input limits. Each file test confirmed unchanged input bytes. Use a saved list that will not change during reading.

For the next experiment, use the same list with two different prefix lengths and compare the results. Change only the network argument, not the file, so you can see exactly how the range changes.

References