cidr-block
v2.3.0
Published
IPv4 and IPv6 address and cidr range utilities
Downloads
36,363
Maintainers
Readme
IPv4 and IPv6 address and CIDR range utilities for JavaScript and TypeScript.
Installation
npm install cidr-blockFeatures
- 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';
// Create and work with IPv4 addresses
const addr = ipv4.address('192.168.1.1');
console.log(addr.isPrivateAddress()); // true
// Create and work with CIDR blocks
const cidr = ipv4.cidr('10.0.0.0/16');
console.log(cidr.addressCount()); // 65536
// IPv6 works the same way
const v6addr = ipv6.address('2001:db8::1');
console.log(v6addr.toString()); // "2001:db8::1"API Reference
Full documentation can be found at cidr-block.com.
IPv4
Creating Addresses
import { ipv4 } from 'cidr-block';
// From string
const addr1 = ipv4.address('192.168.1.1');
// From number
const addr2 = ipv4.address(3232235777);
// From octet array
const addr3 = ipv4.address([192, 168, 1, 1]);Address Validation
import { ipv4 } from 'cidr-block';
ipv4.isValidAddress('192.168.1.1'); // true
ipv4.isValidAddress('256.1.1.1'); // false
ipv4.isValidAddress([10, 0, 0, 1]); // true
ipv4.isValidAddress(4294967295); // true (255.255.255.255)
ipv4.isValidAddress(4294967296); // false (exceeds max)Address Conversion
import { ipv4 } from 'cidr-block';
const addr = ipv4.address('192.168.1.1');
addr.toString(); // "192.168.1.1"
addr.toNumber(); // 3232235777
addr.octets(); // [192, 168, 1, 1]
addr.toBinaryString(); // "11000000.10101000.00000001.00000001"Address Type Detection
import { ipv4 } from 'cidr-block';
// Private addresses (RFC 1918)
ipv4.address('10.0.0.1').isPrivateAddress(); // true
ipv4.address('172.16.0.1').isPrivateAddress(); // true
ipv4.address('192.168.0.1').isPrivateAddress(); // true
ipv4.address('8.8.8.8').isPrivateAddress(); // false
// Loopback addresses
ipv4.address('127.0.0.1').isLoopbackAddress(); // true
ipv4.address('127.255.255.255').isLoopbackAddress(); // true
// Link-local addresses
ipv4.address('169.254.1.1').isLocalLinkAddress(); // true
// Multicast addresses
ipv4.address('224.0.0.1').isMulticastAddress(); // true
ipv4.address('239.255.255.255').isMulticastAddress(); // trueAddress 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'); // true
addr1.equals(addr2); // false
addr1.isLessThan(addr2); // true
addr1.isGreaterThan(addr2); // false
addr1.isLessThanOrEqual(addr2); // true
addr1.isGreaterThanOrEqual(addr2); // falseAddress Navigation
import { ipv4 } from 'cidr-block';
const addr = ipv4.address('192.168.1.100');
addr.hasNextAddress(); // true
addr.nextAddress()?.toString(); // "192.168.1.101"
addr.hasPreviousAddress(); // true
addr.previousAddress()?.toString(); // "192.168.1.99"
// Edge cases
const maxAddr = ipv4.address('255.255.255.255');
maxAddr.hasNextAddress(); // false
maxAddr.nextAddress(); // undefined
const minAddr = ipv4.address('0.0.0.0');
minAddr.hasPreviousAddress(); // false
minAddr.previousAddress(); // undefinedCreating CIDR Blocks
import { ipv4 } from 'cidr-block';
// From string
const cidr1 = ipv4.cidr('192.168.0.0/24');
// From object
const cidr2 = ipv4.cidr({ address: '192.168.0.0', range: 24 });
// From tuple
const cidr3 = ipv4.cidr(['192.168.0.0', 24]);
// Mixed formats work too
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'); // true
ipv4.isValidCIDR('192.168.0.0/33'); // false (range exceeds 32)
ipv4.isValidCIDR('256.0.0.0/24'); // false (invalid address)
ipv4.isValidCIDR(['10.0.0.0', 8]); // trueCIDR Properties
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.0.0/24');
cidr.toString(); // "192.168.0.0/24"
cidr.baseAddress().toString(); // "192.168.0.0"
cidr.range(); // 24
cidr.netmask().toString(); // "255.255.255.0"
cidr.hostmask().toString(); // "0.0.0.255"
cidr.addressCount(); // 256
cidr.rangeParts(); // [Ipv4Address, 24]
// Calculate network address from CIDR with host bits
const hostCidr = ipv4.cidr('192.168.1.5/24');
hostCidr.network().toString(); // "192.168.1.0"
hostCidr.networkCIDR().toString(); // "192.168.1.0/24"Usable Addresses
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.1.0/24');
// First usable (excludes network address)
cidr.getFirstUsableAddress()?.toString(); // "192.168.1.1"
// Last usable (excludes broadcast address)
cidr.getLastUsableAddress()?.toString(); // "192.168.1.254"
// For /32, there are no usable addresses
const hostCidr = ipv4.cidr('192.168.1.1/32');
hostCidr.getFirstUsableAddress(); // undefined
hostCidr.getLastUsableAddress(); // undefinedIterating Addresses
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.1.0/30');
// Using the generator
for (const addr of cidr.addresses()) {
console.log(addr.toString());
}
// Output:
// 192.168.1.0
// 192.168.1.1
// 192.168.1.2
// 192.168.1.3
// Convert to array
const allAddresses = [...cidr.addresses()];
console.log(allAddresses.length); // 4Address Containment
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.0.0/24');
cidr.includes(ipv4.address('192.168.0.100')); // true
cidr.includes(ipv4.address('192.168.1.1')); // false
cidr.includes(ipv4.address('192.168.0.0')); // true
cidr.includes(ipv4.address('192.168.0.255')); // trueCIDR 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); // true (cidr2 is a subnet of cidr1)
cidr1.overlaps(cidr3); // false (different networks)
// Also accepts string format
cidr1.overlaps('10.0.0.0/8'); // falseSubnetting
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.0.0/24');
// Split into equal subnets
const subnets = cidr.subnet(26);
subnets.forEach(s => console.log(s.toString()));
// Output:
// 192.168.0.0/26
// 192.168.0.64/26
// 192.168.0.128/26
// 192.168.0.192/26
// Split into variable-sized subnets
const varSubnets = cidr.subnetBy([26, 27, 27, 26]);
varSubnets.forEach(s => console.log(s.toString()));
// Output:
// 192.168.0.0/26
// 192.168.0.64/27
// 192.168.0.96/27
// 192.168.0.128/26CIDR Navigation
import { ipv4 } from 'cidr-block';
const cidr = ipv4.cidr('192.168.0.0/24');
cidr.hasNextCIDR(); // true
cidr.nextCIDR()?.toString(); // "192.168.1.0/24"
cidr.hasPreviousCIDR(); // true
cidr.previousCIDR()?.toString(); // "192.167.255.0/24"IPv6
Creating Addresses
import { ipv6 } from 'cidr-block';
// From string (with :: compression)
const addr1 = ipv6.address('2001:db8::1');
// From full string
const addr2 = ipv6.address('2001:0db8:0000:0000:0000:0000:0000:0001');
// From BigInt
const addr3 = ipv6.address(42540766411282592856903984951653826561n);
// From hextets array
const addr4 = ipv6.address([0x2001, 0x0db8, 0, 0, 0, 0, 0, 1]);Address Validation
import { ipv6 } from 'cidr-block';
ipv6.isValidAddress('2001:db8::1'); // true
ipv6.isValidAddress('::1'); // true
ipv6.isValidAddress('::'); // true
ipv6.isValidAddress('::ffff:192.168.1.1'); // true (IPv4-mapped)
ipv6.isValidAddress('2001:db8::g'); // false (invalid hex)
ipv6.isValidAddress('2001:db8:::1'); // false (multiple ::)Address Conversion
import { ipv6 } from 'cidr-block';
const addr = ipv6.address('2001:db8::1');
addr.toString(); // "2001:db8::1" (compressed)
addr.toFullString(); // "2001:0db8:0000:0000:0000:0000:0000:0001"
addr.toBigInt(); // 42540766411282592856903984951653826561n
addr.hextets(); // [8193, 3512, 0, 0, 0, 0, 0, 1]
addr.toBinaryString(); // Binary representation with colonsAddress Type Detection
import { ipv6 } from 'cidr-block';
// Loopback
ipv6.address('::1').isLoopbackAddress(); // true
// Unspecified
ipv6.address('::').isUnspecifiedAddress(); // true
// Unique local (private equivalent)
ipv6.address('fc00::1').isUniqueLocalAddress(); // true
ipv6.address('fd00::1').isUniqueLocalAddress(); // true
// Link-local
ipv6.address('fe80::1').isLinkLocalAddress(); // true
// Multicast
ipv6.address('ff02::1').isMulticastAddress(); // true
// IPv4-mapped
ipv6.address('::ffff:192.168.1.1').isIPv4MappedAddress(); // true
// Documentation
ipv6.address('2001:db8::1').isDocumentationAddress(); // trueAddress 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'); // true
addr1.equals(addr2); // false
addr1.isLessThan(addr2); // true
addr1.isGreaterThan(addr2); // false
addr1.isLessThanOrEqual(addr2); // true
addr1.isGreaterThanOrEqual(addr2); // falseAddress Navigation
import { ipv6 } from 'cidr-block';
const addr = ipv6.address('2001:db8::1');
addr.hasNextAddress(); // true
addr.nextAddress()?.toString(); // "2001:db8::2"
addr.hasPreviousAddress(); // true
addr.previousAddress()?.toString(); // "2001:db8::"Creating CIDR Blocks
import { ipv6 } from 'cidr-block';
// From string
const cidr1 = ipv6.cidr('2001:db8::/32');
// From object
const cidr2 = ipv6.cidr({ address: '2001:db8::', range: 32 });
// From tuple
const cidr3 = ipv6.cidr(['2001:db8::', 32]);CIDR Validation
import { ipv6 } from 'cidr-block';
ipv6.isValidCIDR('2001:db8::/32'); // true
ipv6.isValidCIDR('2001:db8::/129'); // false (range exceeds 128)
ipv6.isValidCIDR(['::1', 128]); // trueCIDR Properties
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/32');
cidr.toString(); // "2001:db8::/32"
cidr.baseAddress().toString(); // "2001:db8::"
cidr.range(); // 32
cidr.netmask().toString(); // "ffff:ffff::"
cidr.hostmask().toString(); // "::ffff:ffff:ffff:ffff:ffff:ffff"
cidr.addressCount(); // 79228162514264337593543950336n (BigInt)
// Calculate network address from CIDR with host bits
const hostCidr = ipv6.cidr('2001:db8::1234/32');
hostCidr.network().toString(); // "2001:db8::"
hostCidr.networkCIDR().toString(); // "2001:db8::/32"Usable Addresses
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/126');
cidr.getFirstUsableAddress()?.toString(); // "2001:db8::1"
cidr.getLastUsableAddress()?.toString(); // "2001:db8::2"
// For /128, there are no usable addresses
const hostCidr = ipv6.cidr('2001:db8::1/128');
hostCidr.getFirstUsableAddress(); // undefined
hostCidr.getLastUsableAddress(); // undefinedIterating Addresses
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/126');
for (const addr of cidr.addresses()) {
console.log(addr.toString());
}
// Output:
// 2001:db8::
// 2001:db8::1
// 2001:db8::2
// 2001:db8::3
// With limit (useful for large ranges)
for (const addr of cidr.addresses(2n)) {
console.log(addr.toString());
}
// Output:
// 2001:db8::
// 2001:db8::1Address Containment and Overlap
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/32');
cidr.includes(ipv6.address('2001:db8::1')); // true
cidr.includes(ipv6.address('2001:db9::1')); // false
const cidr2 = ipv6.cidr('2001:db8:1::/48');
cidr.overlaps(cidr2); // trueSubnetting
import { ipv6 } from 'cidr-block';
const cidr = ipv6.cidr('2001:db8::/32');
// Split into /34 subnets
const subnets = cidr.subnet(34);
subnets.forEach(s => console.log(s.toString()));
// Output:
// 2001:db8::/34
// 2001:db8:4000::/34
// 2001:db8:8000::/34
// 2001:db8:c000::/34
// Variable-sized subnets
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(); // true
cidr.nextCIDR()?.toString(); // "2001:db9::/32"
cidr.hasPreviousCIDR(); // true
cidr.previousCIDR()?.toString(); // "2001:db7::/32"Error Handling
import {
ipv4,
ipv6,
InvalidIpv4AddressError,
InvalidIpv4CidrError,
InvalidIpv4CidrRangeError,
InvalidIpv6AddressError,
InvalidIpv6CidrError,
InvalidIpv6CidrRangeError
} from 'cidr-block';
// Invalid address throws error
try {
ipv4.address('256.0.0.1');
} catch (e) {
if (e instanceof InvalidIpv4AddressError) {
console.log(e.message); // "256.0.0.1 is not a valid IPv4 address"
}
}
// Invalid CIDR throws error
try {
ipv4.cidr('192.168.0.0/33');
} catch (e) {
if (e instanceof InvalidIpv4CidrError) {
console.log(e.message); // "192.168.0.0/33 is not a valid IPv4 CIDR range"
}
}
// Invalid subnet operation throws error
try {
const cidr = ipv4.cidr('192.168.0.0/24');
cidr.subnet(20); // Can't create larger subnets
} catch (e) {
if (e instanceof InvalidIpv4CidrRangeError) {
console.log('Invalid subnet range');
}
}
// Use validation to avoid exceptions
if (ipv4.isValidAddress(userInput)) {
const addr = ipv4.address(userInput);
// Safe to use
}Constants
import { ipv4, ipv6 } from 'cidr-block';
// IPv4 constants
ipv4.MAX_SIZE; // 0xffffffff (4294967295)
ipv4.MIN_SIZE; // 0x00000000
ipv4.MAX_RANGE; // 32
ipv4.MIN_RANGE; // 0
// IPv6 constants
ipv6.MAX_SIZE; // (1n << 128n) - 1n
ipv6.MIN_SIZE; // 0n
ipv6.MAX_RANGE; // 128
ipv6.MIN_RANGE; // 0Type Definitions
import type {
// IPv4 types
Ipv4AddressLiteral, // string | number | number[]
Ipv4AddressString, // "${number}.${number}.${number}.${number}"
Ipv4AddressOctets, // [number, number, number, number]
Ipv4CidrLiteral, // string | { address, range } | [address, range]
Ipv4CidrString, // "${number}.${number}.${number}.${number}/${number}"
// IPv6 types
Ipv6AddressLiteral, // string | bigint | number[]
Ipv6AddressHextets, // [number, number, number, number, number, number, number, number]
Ipv6CidrLiteral, // string | { address, range } | [address, range]
} 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'); // true
isInternalIP('10.0.0.1'); // true
isInternalIP('8.8.8.8'); // falseAllocating 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()));
// 10.0.0.0/24
// 10.0.1.0/24
// 10.0.2.0/24Checking 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);
// ['10.0.0.0/24', '10.0.1.0/24']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()) {
// Skip network and broadcast addresses for practical use
if (addr.equals(cidr.baseAddress())) continue;
const lastOctet = addr.octets()[3];
if (lastOctet === 255) continue; // Skip broadcast
ips.push(addr.toString());
}
return ips;
}
const usable = getUsableIPs('192.168.1.0/29');
// ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4', '192.168.1.5', '192.168.1.6']Normalizing CIDR Blocks
import { ipv4, ipv6 } from 'cidr-block';
// Normalize IPv4 CIDR by removing host bits
function normalizeIPv4CIDR(cidrStr: string): string {
const cidr = ipv4.cidr(cidrStr);
return cidr.networkCIDR().toString();
}
normalizeIPv4CIDR('192.168.1.5/24'); // "192.168.1.0/24"
normalizeIPv4CIDR('10.5.10.20/8'); // "10.0.0.0/8"
normalizeIPv4CIDR('172.16.50.100/12'); // "172.16.0.0/12"
// Normalize IPv6 CIDR by removing host bits
function normalizeIPv6CIDR(cidrStr: string): string {
const cidr = ipv6.cidr(cidrStr);
return cidr.networkCIDR().toString();
}
normalizeIPv6CIDR('2001:db8::1234/32'); // "2001:db8::/32"
normalizeIPv6CIDR('2001:db8:1:2:3:4:5:6/64'); // "2001:db8:1:2::/64"
normalizeIPv6CIDR('2001:db8:abcd:ef01::/48'); // "2001:db8:abcd::/48"