IPv4 and IPv6 address and CIDR range utilities for JavaScript and TypeScript.
Installation
npm install cidr-block
Features
- Full IPv4 and IPv6 address support
- CIDR block creation and manipulation
- Address validation and parsing
- Network calculations (netmask, hostmask, address count, usable addresses)
- Subnetting operations
- Address type detection (private, loopback, multicast, etc.)
- Full TypeScript support with comprehensive type definitions
- Zero dependencies
- Works with ESM and CommonJS
Quick Start
import { ipv4, ipv6 } from 'cidr-block';
const addr = ipv4.address('192.168.1.1');
console.log(addr.isPrivateAddress());
const cidr = ipv4.cidr('10.0.0.0/16');
console.log(cidr.addressCount());
const v6addr = ipv6.address('2001:db8::1');
console.log(v6addr.toString());
API Reference
Full documentation can be found at cidr-block.com.
IPv4
Creating Addresses
import { ipv4 } from 'cidr-block';
const addr1 = ipv4.address('192.168.1.1');
const addr2 = ipv4.address(3232235777);
const addr3 = ipv4.address([192, 168, 1, 1]);
Address Validation
import { ipv4 } from 'cidr-block';
ipv4.isValidAddress('192.168.1.1');
ipv4.isValidAddress('256.1.1.1');
ipv4.isValidAddress([10, 0, 0, 1]);
ipv4.isValidAddress(4294967295);
ipv4.isValidAddress(4294967296);
Address Conversion
import { ipv4 } from 'cidr-block';
const addr = ipv4.address('192.168.1.1');
addr.toString();
addr.toNumber();
addr.octets();
addr.toBinaryString();
Address Type Detection
import { ipv4 } from 'cidr-block';
ipv4.address('10.0.0.1').isPrivateAddress();
ipv4.address('172.16.0.1').isPrivateAddress();
ipv4.address('192.168.0.1').isPrivateAddress();
ipv4.address('8.8.8.8').isPrivateAddress();
ipv4.address('127.0.0.1').isLoopbackAddress();
ipv4.address('127.255.255.255').isLoopbackAddress();
ipv4.address('169.254.1.1').isLocalLinkAddress();
ipv4.address('224.0.0.1').isMulticastAddress();
ipv4.address('239.255.255.255').isMulticastAddress();
Address Comparison
import { ipv4 } from 'cidr-block';
const addr1 = ipv4.address('192.168.1.1');
const addr2 = ipv4.address('192.168.1.2');
addr1.equals('192.168.1.1');
addr1.equals(addr2);
addr1.isLessThan(addr2);
addr1.isGreaterThan(addr2);
addr1.isLessThanOrEqual(addr2);
addr1.isGreaterThanOrEqual(addr2);
Address Navigation
import { ipv4 } from 'cidr-block';
const addr = ipv4.address('192.168.1.100');
addr.hasNextAddress();
addr.nextAddress()?.toString();
addr.hasPreviousAddress();
addr.previousAddress()?.toString();
const maxAddr = ipv4.address('255.255.255.255');
maxAddr.hasNextAddress();
maxAddr.nextAddress();
const minAddr = ipv4.address('0.0.0.0');
minAddr.hasPreviousAddress();
minAddr.previousAddress();
Creating CIDR Blocks
import { ipv4 } from 'cidr-block';
const cidr1 = ipv4.cidr('192.168.0.0/24');
const cidr2 = ipv4.cidr({ address: '192.168.0.0', range: 24 });
const cidr3 = ipv4.cidr(['192.168.0.0', 24]);
const cidr4 = ipv4.cidr({ address: [192, 168, 0, 0], range: 24 });
CIDR Validation
import { ipv4 } from 'cidr-block';
ipv4.isValidCIDR('192.168.0.0/24');
ipv4.isValidCIDR('192.168.0.0/33');
ipv4.isValidCIDR('256.0.0.0/24');
ipv4.isValidCIDR(['10.0.0.0', 8]);
CIDR Properties
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.0.0/24');
cidr.toString();
cidr.baseAddress().toString();
cidr.range();
cidr.netmask().toString();
cidr.hostmask().toString();
cidr.addressCount();
cidr.rangeParts();
const hostCidr = ipv4.cidr('192.168.1.5/24');
hostCidr.network().toString();
hostCidr.networkCIDR().toString();
Usable Addresses
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.1.0/24');
cidr.getFirstUsableAddress()?.toString();
cidr.getLastUsableAddress()?.toString();
const hostCidr = ipv4.cidr('192.168.1.1/32');
hostCidr.getFirstUsableAddress();
hostCidr.getLastUsableAddress();
Iterating Addresses
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.1.0/30');
for (const addr of cidr.addresses()) {
console.log(addr.toString());
}
const allAddresses = [...cidr.addresses()];
console.log(allAddresses.length);
Address Containment
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.0.0/24');
cidr.includes(ipv4.address('192.168.0.100'));
cidr.includes(ipv4.address('192.168.1.1'));
cidr.includes(ipv4.address('192.168.0.0'));
cidr.includes(ipv4.address('192.168.0.255'));
CIDR Overlap Detection
import { ipv4 } from 'cidr-block';
const cidr1 = ipv4.cidr('192.168.0.0/24');
const cidr2 = ipv4.cidr('192.168.0.128/25');
const cidr3 = ipv4.cidr('192.168.1.0/24');
cidr1.overlaps(cidr2);
cidr1.overlaps(cidr3);
cidr1.overlaps('10.0.0.0/8');
Subnetting
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.0.0/24');
const subnets = cidr.subnet(26);
subnets.forEach(s => console.log(s.toString()));
const varSubnets = cidr.subnetBy([26, 27, 27, 26]);
varSubnets.forEach(s => console.log(s.toString()));
CIDR Navigation
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.0.0/24');
cidr.hasNextCIDR();
cidr.nextCIDR()?.toString();
cidr.hasPreviousCIDR();
cidr.previousCIDR()?.toString();
IPv6
Creating Addresses
import { ipv6 } from 'cidr-block';
const addr1 = ipv6.address('2001:db8::1');
const addr2 = ipv6.address('2001:0db8:0000:0000:0000:0000:0000:0001');
const addr3 = ipv6.address(42540766411282592856903984951653826561n);
const addr4 = ipv6.address([0x2001, 0x0db8, 0, 0, 0, 0, 0, 1]);
Address Validation
import { ipv6 } from 'cidr-block';
ipv6.isValidAddress('2001:db8::1');
ipv6.isValidAddress('::1');
ipv6.isValidAddress('::');
ipv6.isValidAddress('::ffff:192.168.1.1');
ipv6.isValidAddress('2001:db8::g');
ipv6.isValidAddress('2001:db8:::1');
Address Conversion
import { ipv6 } from 'cidr-block';
const addr = ipv6.address('2001:db8::1');
addr.toString();
addr.toFullString();
addr.toBigInt();
addr.hextets();
addr.toBinaryString();
Address Type Detection
import { ipv6 } from 'cidr-block';
ipv6.address('::1').isLoopbackAddress();
ipv6.address('::').isUnspecifiedAddress();
ipv6.address('fc00::1').isUniqueLocalAddress();
ipv6.address('fd00::1').isUniqueLocalAddress();
ipv6.address('fe80::1').isLinkLocalAddress();
ipv6.address('ff02::1').isMulticastAddress();
ipv6.address('::ffff:192.168.1.1').isIPv4MappedAddress();
ipv6.address('2001:db8::1').isDocumentationAddress();
Address Comparison
import { ipv6 } from 'cidr-block';
const addr1 = ipv6.address('2001:db8::1');
const addr2 = ipv6.address('2001:db8::2');
addr1.equals('2001:db8::1');
addr1.equals(addr2);
addr1.isLessThan(addr2);
addr1.isGreaterThan(addr2);
addr1.isLessThanOrEqual(addr2);
addr1.isGreaterThanOrEqual(addr2);
Address Navigation
import { ipv6 } from 'cidr-block';
const addr = ipv6.address('2001:db8::1');
addr.hasNextAddress();
addr.nextAddress()?.toString();
addr.hasPreviousAddress();
addr.previousAddress()?.toString();
Creating CIDR Blocks
import { ipv6 } from 'cidr-block';
const cidr1 = ipv6.cidr('2001:db8::/32');
const cidr2 = ipv6.cidr({ address: '2001:db8::', range: 32 });
const cidr3 = ipv6.cidr(['2001:db8::', 32]);
CIDR Validation
import { ipv6 } from 'cidr-block';
ipv6.isValidCIDR('2001:db8::/32');
ipv6.isValidCIDR('2001:db8::/129');
ipv6.isValidCIDR(['::1', 128]);
CIDR Properties
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/32');
cidr.toString();
cidr.baseAddress().toString();
cidr.range();
cidr.netmask().toString();
cidr.hostmask().toString();
cidr.addressCount();
const hostCidr = ipv6.cidr('2001:db8::1234/32');
hostCidr.network().toString();
hostCidr.networkCIDR().toString();
Usable Addresses
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/126');
cidr.getFirstUsableAddress()?.toString();
cidr.getLastUsableAddress()?.toString();
const hostCidr = ipv6.cidr('2001:db8::1/128');
hostCidr.getFirstUsableAddress();
hostCidr.getLastUsableAddress();
Iterating Addresses
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/126');
for (const addr of cidr.addresses()) {
console.log(addr.toString());
}
for (const addr of cidr.addresses(2n)) {
console.log(addr.toString());
}
Address Containment and Overlap
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/32');
cidr.includes(ipv6.address('2001:db8::1'));
cidr.includes(ipv6.address('2001:db9::1'));
const cidr2 = ipv6.cidr('2001:db8:1::/48');
cidr.overlaps(cidr2);
Subnetting
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/32');
const subnets = cidr.subnet(34);
subnets.forEach(s => console.log(s.toString()));
const varSubnets = cidr.subnetBy([34, 34, 33]);
varSubnets.forEach(s => console.log(s.toString()));
CIDR Navigation
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/32');
cidr.hasNextCIDR();
cidr.nextCIDR()?.toString();
cidr.hasPreviousCIDR();
cidr.previousCIDR()?.toString();
Error Handling
import {
ipv4,
ipv6,
InvalidIpv4AddressError,
InvalidIpv4CidrError,
InvalidIpv4CidrRangeError,
InvalidIpv6AddressError,
InvalidIpv6CidrError,
InvalidIpv6CidrRangeError
} from 'cidr-block';
try {
ipv4.address('256.0.0.1');
} catch (e) {
if (e instanceof InvalidIpv4AddressError) {
console.log(e.message);
}
}
try {
ipv4.cidr('192.168.0.0/33');
} catch (e) {
if (e instanceof InvalidIpv4CidrError) {
console.log(e.message);
}
}
try {
const cidr = ipv4.cidr('192.168.0.0/24');
cidr.subnet(20);
} catch (e) {
if (e instanceof InvalidIpv4CidrRangeError) {
console.log('Invalid subnet range');
}
}
if (ipv4.isValidAddress(userInput)) {
const addr = ipv4.address(userInput);
}
Constants
import { ipv4, ipv6 } from 'cidr-block';
ipv4.MAX_SIZE;
ipv4.MIN_SIZE;
ipv4.MAX_RANGE;
ipv4.MIN_RANGE;
ipv6.MAX_SIZE;
ipv6.MIN_SIZE;
ipv6.MAX_RANGE;
ipv6.MIN_RANGE;
Type Definitions
import type {
Ipv4AddressLiteral,
Ipv4AddressString,
Ipv4AddressOctets,
Ipv4CidrLiteral,
Ipv4CidrString,
Ipv6AddressLiteral,
Ipv6AddressHextets,
Ipv6CidrLiteral,
} from 'cidr-block';
Common Use Cases
Checking if an IP is in a Private Network
import { ipv4 } from 'cidr-block';
function isInternalIP(ip: string): boolean {
if (!ipv4.isValidAddress(ip)) return false;
const addr = ipv4.address(ip);
return addr.isPrivateAddress() || addr.isLoopbackAddress();
}
isInternalIP('192.168.1.1');
isInternalIP('10.0.0.1');
isInternalIP('8.8.8.8');
Allocating Subnets from a Pool
import { ipv4 } from 'cidr-block';
function allocateSubnets(poolCidr: string, subnetSize: number, count: number) {
const pool = ipv4.cidr(poolCidr);
const subnets = pool.subnet(subnetSize);
return subnets.slice(0, count);
}
const allocated = allocateSubnets('10.0.0.0/16', 24, 3);
allocated.forEach(s => console.log(s.toString()));
Checking for CIDR Conflicts
import { ipv4, Ipv4Cidr } from 'cidr-block';
function findConflicts(newCidr: string, existing: string[]): string[] {
const cidr = ipv4.cidr(newCidr);
return existing.filter(e => cidr.overlaps(e));
}
const existingRanges = ['10.0.0.0/24', '10.0.1.0/24', '192.168.0.0/16'];
const conflicts = findConflicts('10.0.0.0/16', existingRanges);
Generating IP Addresses in a Range
import { ipv4 } from 'cidr-block';
function getUsableIPs(cidrStr: string): string[] {
const cidr = ipv4.cidr(cidrStr);
const ips: string[] = [];
for (const addr of cidr.addresses()) {
if (addr.equals(cidr.baseAddress())) continue;
const lastOctet = addr.octets()[3];
if (lastOctet === 255) continue;
ips.push(addr.toString());
}
return ips;
}
const usable = getUsableIPs('192.168.1.0/29');
Normalizing CIDR Blocks
import { ipv4, ipv6 } from 'cidr-block';
function normalizeIPv4CIDR(cidrStr: string): string {
const cidr = ipv4.cidr(cidrStr);
return cidr.networkCIDR().toString();
}
normalizeIPv4CIDR('192.168.1.5/24');
normalizeIPv4CIDR('10.5.10.20/8');
normalizeIPv4CIDR('172.16.50.100/12');
function normalizeIPv6CIDR(cidrStr: string): string {
const cidr = ipv6.cidr(cidrStr);
return cidr.networkCIDR().toString();
}
normalizeIPv6CIDR('2001:db8::1234/32');
normalizeIPv6CIDR('2001:db8:1:2:3:4:5:6/64');
normalizeIPv6CIDR('2001:db8:abcd:ef01::/48');