# IPAddress: a Java library for IPv4 and IPv6 addresses, subnets and ranges

> IPAddress is a long-lived Java library for manipulating IP addresses and subnets, covering CIDR, address ranges, iterators, containment checks, longest prefix match, subnetting and address tries with the same code working for IPv4 and IPv6. The surface area is enormous and the version history is a sequence of behavioural changes you need to read before upgrading.

**seancfoley/IPAddress** — Java library for handling IP addresses and subnets, both IPv4 and IPv6

- Repository: https://github.com/seancfoley/IPAddress
- Website: https://seancfoley.github.io/IPAddress/
- Stars: 539 · Forks: 72
- Language: Java
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/seancfoley-ipaddress

## One API for addresses, subnets, ranges and tries

IPAddress is a Java library for handling IP addresses and subnets, both IPv4 and IPv6. The README summarises the scope in one long line: IP address and network manipulations, CIDR, address and subnet operations, address ranges, iterators, containment checks, longest prefix match, subnetting, address tries, address collections, and more, with polymorphic code.

That last clause is the interesting one. The same method names work across address types, and the same code paths work for both address families, which is the problem this library exists to solve. A codebase that parses IPv4 with java.net.InetAddress and IPv6 with something else ends up with two code paths, two sets of bugs, and a lot of code that only knows how to compare two dotted quads. Here an IPAddress object and an IPAddressNetwork object are polymorphic over the family, so a subnetting routine written once works for both.

The distribution is ordinary Maven. The group id is com.github.seancfoley, the artifact id is ipaddress, and the library is packaged as an OSGI bundle, with the OSGI bundle available since version 5.3.1. There is also a Linux Fedora rpm listed, and a separate Go implementation lives in the ipaddress-go repository, which is worth knowing about if your infrastructure is not JVM based.

The documentation is spread across several places. There is a documentation site, a code examples wiki, and generated Javadoc. The README also links a list of users, which is the sort of thing a project with a long history tends to accumulate.

The audience is a backend Java developer who has to deal with networks as data rather than as strings, which in practice means firewall rules, routing tables, IP allow lists, geolocation databases and audit logs that all store addresses in CIDR notation.

## Parsing strings and the two ways to resolve a host name

The starting point is the IPAddressString class, which wraps a string and converts it to an address or a network. Malformed input is handled with a checked exception, and the example shows the pattern:

```java
String ipv6Str = "::/64";
String ipv4Str = "1.2.255.4/255.255.0.0";
try {
	IPAddress ipv6Address = new IPAddressString(ipv6Str).toAddress();
	IPAddress ipv4Address = new IPAddressString(ipv4Str).toAddress();
        // use addresses
} catch (AddressStringException e) {
	String msg = e.getMessage();//detailed message indicating improper string format
	// handle improperly formatted address string
}
```

The second string is worth pausing on. A mask written as 255.255.0.0 is a netmask, and the library has to decide whether that denotes a prefix block or a single address with a mask attached. That decision changed between major versions, which is exactly the kind of detail that bites during an upgrade, and it is covered later here.

The HostName class covers the other direction, and it separates two things that are often conflated. asAddress does not resolve, it just parses, while toAddress resolves if necessary:

```java
	host = new HostName(hostAddressStr);
	IPAddress address = host.asAddress(); // does not resolve
	// use address
	host = new HostName(dnsStr);
	address = host.toAddress(); // resolves if necessary
```

That distinction is a real safety property in server code. A method that silently performs a DNS lookup when you only meant to parse a string can block for seconds, can be tricked into a lookup against an attacker-controlled name, and can throw UnknownHostException in a path you thought was pure parsing. The library gives you both behaviours and lets you choose. The same class also handles the bracketed host and port form and the service form, converting to an InetSocketAddress, with a service resolver callback so a symbolic service name can be mapped to a port number.

## Installing from Maven and using it from other JVM languages

The library is on Maven Central under the coordinates com.github.seancfoley and ipaddress, and the README links the published versions 2.0.2, 3.0.0, 4.3.3 and 5.6.2, with the latest listed as 5.6.2. The releases are 5.6.2 on 2026-03-15, 5.6.1 on 2026-02-02 and 5.6.0 on 2026-02-01, and the last push to the repository was on 2026-09-07.

The code itself is Java, but the README notes that as a Java library it is interoperable with Kotlin, Scala, Groovy and Clojure, and the header carries logos for Java, Kotlin, Go, Scala, Groovy and Clojure. The Kotlin example in the README is a direct translation of the Java one, using IPAddressString and toAddress inside a try block with an AddressStringException catch. The Go logo points to the separate ipaddress-go repository rather than to this codebase, so the Go support is a port with its own release cycle rather than a binding.

One practical wrinkle is worth knowing before you wire this into a build. The library is compiled with Java 8 but also ships a Java 9 compiled module-info.class file for users of the Java Platform Module System. The README says you may need to, or wish to, delete the module-info when running in Java 8 environments, and it links the specific issue comment and a Gradle recipe for doing it.

That is a small thing that costs an afternoon if you hit it, because a stray module-info in a Java 8 classpath is not a friendly error message. If your build is Java 8 only, check that before you add the dependency rather than after.

## Version 3 and version 4 changed what a prefixed address means

The version table in the README is the most valuable part of the documentation for anyone with an existing codebase, and it is not a summary of features alone.

Version 1.0.1 required Java 6 or higher. Version 2.0.2 moved to Java 8 or higher. Version 3.0.0 kept Java 8 and added MAC address support, EUI-48 and EUI-64 MAC integration with IPv6, a new address framework, and new IP string formats parsed and produced.

Version 4.3.3 is where the semantic change bites. The notes say that IPv4-network, IPv6-subnet-router-anycast and zero-host addresses are interpreted as the prefix block subnet, while other prefixed addresses are individual addresses, and that there exists the option to preserve the version 3 behaviour. So for a subset of address forms, the same input string means something different in version 4 than in version 3, and the old semantics remain reachable by option.

Version 4 also brought new prefix length handling, additional methods for managing prefix blocks, improved parsing performance and a change to the increment(long) behaviour for subnets.

Version 5 is the largest step. It added the sequential range classes, reorganised the classes and interfaces in the inet.ipaddr.format package into standard, large and string subpackages, enhanced address block splitting and merging, added Java 8 stream and spliterator methods, additional parsing options, address tries, associative address tries, containment tries, the prefix block allocator, and sequential range lists.

The practical rule is that a major upgrade here is a semantic review, not a version bump. If your code parses prefixed addresses and compares them, or splits blocks and expects a certain count of results, the upgrade needs tests written against the old behaviour before the dependency changes.

## What the version 5 feature list actually gives you

It is easy to read the version 5 notes as a shopping list, so it is worth grouping what you actually get as a developer.

The address operations are the base layer: parsing and producing addresses and prefixes, iterating them, checking containment, and computing the longest prefix match, which is the operation that answers the question of which of a set of networks contains a given address.

Address tries and their relatives are the indexing layer. A trie over addresses lets you look up a prefix match in logarithmic rather than linear time, which is how a routing table or an allow list is implemented. The associative address tries and containment tries are variants for the cases where you need to store something alongside the prefix or test membership without walking the structure manually.

The prefix block allocator and the enhanced splitting and merging are the subnetting layer, and the sequential range classes and sequential range lists cover the case of contiguous address space that is not a single prefix, which is common in real allow lists and in allocation records.

The format package reorganisation is worth noting separately because it is a source-breaking change. The classes and interfaces in inet.ipaddr.format were split into standard, large and string subpackages, so any code importing those types by their old fully qualified name needs updating. The added parsing options and the Java 8 stream and spliterator methods are the modern conveniences layered on top.

Taken together, this is a library with a very large surface, and that is the point and the problem. Almost anything you would otherwise write yourself for IP arithmetic is here, already tested, and it works the same for both address families.

## Where this library is the wrong choice

Three situations call for something else, and it is worth being clear about them.

The first is a one-off parse. If you need to read a single address from a configuration file and check that it is well formed, java.net.InetAddress or a few lines of your own code is enough, and adding a library with this much surface to your build for that is a poor trade. The cost of IPAddress shows up in the dependency graph, in the API you have to learn, and in the upgrade conversations when a major version lands.

The second is a hard real-time or a memory-constrained environment. The library models a lot of things, tries, ranges, prefix blocks, MAC addresses, format subpackages, and the objects carry their own state. If you are parsing millions of addresses in a tight loop on a small device, the simpler approach wins.

The third is that the documentation is spread thin. The README does not contain a feature walkthrough or a tutorial, it points to a documentation site, a wiki with code examples, and generated Javadoc. That is normal for a mature library, and it is also a real cost when you are deciding whether to adopt it. Reading the code examples wiki and the Javadoc is a prerequisite rather than an option.

There is one more limit specific to the Java story. The Go implementation is a separate repository with its own versions and its own API, so a team with both a Go service and a Java service in the same estate is looking at two libraries rather than one, and the two will not share a type system. The README positions the Go version as available, and the interoperability across JVM languages is the strength, but the JVM is the primary target and the code base here is the Java one.

## Conclusion

Adopt IPAddress if your Java code has to parse, compare, iterate or split IP addresses and subnets and you want one implementation that covers IPv4 and IPv6 rather than two. Do not adopt it if your needs are a single parse of a well-formed string, where the standard library and a few lines of code are cheaper, and do not upgrade across a major version without reading the release notes first, since version 3 and version 4 changed parsing and prefix semantics. Verify first that the version you pick supports your Java runtime, that the prefix block interpretation matches what your data means, and that the API surface you need is present in the version you pin, not only in the newest one.

## FAQ

### How do I add the IPAddress library to a Java project?

Add it from Maven Central with group id com.github.seancfoley and artifact id ipaddress. The README links published versions including 2.0.2, 3.0.0, 4.3.3 and 5.6.2, and the library is also packaged as an OSGI bundle.

### Does IPAddress handle both IPv4 and IPv6 with the same code?

Yes. The README describes the library as providing polymorphic code, so the same operations work across address families for addresses, subnets, ranges, iterators, containment checks, longest prefix match, subnetting and address tries.

### What changed between version 3 and version 4 of IPAddress?

Version 4.3.3 interprets IPv4-network, IPv6-subnet-router-anycast and zero-host addresses as the prefix block subnet, while other prefixed addresses are individual addresses, and an option exists to preserve the version 3 behaviour. It also added prefix length handling, prefix block methods, improved parsing performance and a change to increment(long) for subnets.

### What Java version does the latest IPAddress release need?

Version 5.6.2 requires Java 8 or higher and is compatible with Android at API level 24 or higher. The code is compiled with Java 8 but includes a Java 9 module-info.class, which you may need to delete when running in Java 8 environments.

### Does IPAddress resolve DNS names?

The HostName class offers both behaviours: asAddress parses without resolving, while toAddress resolves if necessary. The README example also shows converting a host with a port or a service name into an InetSocketAddress.

## Sources

- [License: Apache-2.0](https://github.com/seancfoley/IPAddress/blob/master/LICENSE)
- [Project website](https://seancfoley.github.io/IPAddress/)
- [README](https://github.com/seancfoley/IPAddress/blob/master/README.md)
- [Releases](https://github.com/seancfoley/IPAddress/releases)
- [seancfoley/IPAddress on GitHub](https://github.com/seancfoley/IPAddress)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/seancfoley-ipaddress
