zero dependencies · strict TypeScript · ESM + CJS

node-ip-ts

A modern, type-safe IP address utility library for Node.js — a full TypeScript rewrite of the popular ip package.

Key Features

TypeScript Native

Full .d.ts declarations with strict null checks out of the box.

ESM + CJS

Ships both ES Modules and CommonJS builds for any environment.

Zero Dependencies

No runtime dependencies. Lightweight and safe to ship to production.

Get up and running in seconds

npm install node-ip-ts

Requires Node.js ≥ 16

Three ways to import

ESM / TypeScript
import * as ip from 'node-ip-ts';

// Address classification
ip.isPrivate('192.168.1.1');   // true
ip.isPublic('8.8.8.8');        // true
ip.isLoopback('127.0.0.1');    // true

// Subnet operations
ip.cidr('192.168.1.134/26');   // '192.168.1.128'
const subnet = ip.cidrSubnet('192.168.1.134/26');
subnet.contains('192.168.1.180');  // true

// Conversion
ip.toLong('255.255.255.255');  // 4294967295
ip.fromLong(4294967295);       // '255.255.255.255'
Named Imports (tree-shakeable)
import {
  isPrivate,
  cidrSubnet,
  toLong
} from 'node-ip-ts';
CommonJS
const ip = require('node-ip-ts');

ip.isPrivate('10.0.0.1');
// true

Why switch from ip?

Drop-in replacement with full TypeScript support and ES Module compatibility.

Feature ip node-ip-ts
TypeScript supportNoYes
ES Module supportNoYes
CommonJS supportYesYes
Type declarations (.d.ts)NoYes
Strict null checksNoYes
External dependencies00
API compatibilityDrop-in
- const ip = require('ip');
+ const ip = require('node-ip-ts');

// Or for TypeScript / ESM:
import * as ip from 'node-ip-ts';

Works everywhere — almost

All functions except address() work in browser and bundler environments (Vite, webpack, esbuild…).

Function Node.js Browser / Bundler
All IP / subnet / bitwise functions
loopback()
address()uses os module

Complete function reference

Address Classification

isPrivate
(addr: string): boolean

Returns true if the address falls within any private/reserved range: RFC 1918, link-local, IPv6 ULA, IPv6 link-local, loopback.

ip.isPrivate('192.168.0.1');           // true
ip.isPrivate('fd12:3456:789a:1::1');   // true  (IPv6 ULA)
ip.isPrivate('::ffff:192.168.0.1');    // true  (IPv4-mapped IPv6)
ip.isPrivate('8.8.8.8');               // false
isPublic
(addr: string): boolean

Inverse of isPrivate. Returns true for publicly routable addresses.

ip.isPublic('1.1.1.1');   // true
ip.isPublic('10.0.0.1'); // false
isLoopback
(addr: string): boolean

Returns true for loopback addresses. Supports dotted-decimal, octal, hexadecimal, and long-integer notation.

ip.isLoopback('127.0.0.1');  // true
ip.isLoopback('::1');          // true
ip.isLoopback('0x7f.0.0.1');   // true  (hex)
ip.isLoopback('0177.0.0.1');   // true  (octal)
ip.isLoopback('2130706433');   // true  (integer)
isV4Format
(ip: string): boolean
ip.isV4Format('192.168.0.1'); // true
ip.isV4Format('::1');          // false
isV6Format
(ip: string): boolean
ip.isV6Format('::1');              // true
ip.isV6Format('192.168.0.1'); // false

Subnet & CIDR

cidr
(cidrString: string): string

Returns the network address for a given CIDR string.

ip.cidr('192.168.1.134/26');        // '192.168.1.128'
ip.cidr('2607:f0d0:1002:51::4/56'); // '2607:f0d0:1002::'
cidrSubnet
(cidrString: string): SubnetInfo

Returns a full SubnetInfo object for a given CIDR string.

const s = ip.cidrSubnet('192.168.1.134/26');

s.networkAddress;    // '192.168.1.128'
s.firstAddress;      // '192.168.1.129'
s.lastAddress;       // '192.168.1.190'
s.broadcastAddress;  // '192.168.1.191'
s.subnetMask;        // '255.255.255.192'
s.subnetMaskLength;  // 26
s.numHosts;          // 62
s.length;            // 64
s.contains('192.168.1.150'); // true
s.contains('192.168.1.200'); // false
subnet
(addr, mask): SubnetInfo

Same as cidrSubnet but takes address and mask separately.

ip.subnet(
  '192.168.1.134',
  '255.255.255.192'
);
mask
(addr, mask): string

Applies a subnet mask via bitwise AND.

ip.mask(
  '192.168.1.134',
  '255.255.255.0'
); // '192.168.1.0'
fromPrefixLen
(prefixlen: number, family?: string | number): string

Converts a prefix length to a subnet mask string. Auto-detects IPv6 for values > 32.

ip.fromPrefixLen(24);         // '255.255.255.0'
ip.fromPrefixLen(64);         // 'ffff:ffff:ffff:ffff::'
ip.fromPrefixLen(24, 'ipv6'); // 'ffff:ff00::'

Bitwise Operations

not
(addr: string): string

Bitwise NOT — useful for computing wildcard masks.

ip.not('255.255.255.0');  // '0.0.0.255'
or
(a: string, b: string): string

Bitwise OR. Supports same-protocol and mixed IPv4/IPv6 inputs.

ip.or('0.0.0.255', '192.168.1.10');          // '192.168.1.255'
ip.or('::ff', '::abcd:dcba:abcd:dcba');   // '::abcd:dcba:abcd:dcff'
isEqual
(a: string, b: string): boolean

Deep equality check, IPv4/IPv6 aware (e.g. 127.0.0.1 equals ::ffff:7f00:1).

ip.isEqual('127.0.0.1', '::ffff:127.0.0.1'); // true
ip.isEqual('127.0.0.1', '::7f00:1');          // true
ip.isEqual('127.0.0.1', '::7f00:2');          // false

Buffer & Long Integer Conversion

toBuffer
(ip, buff?, offset?): Buffer

Converts an IP string to a raw Buffer (4 bytes IPv4, 16 for IPv6).

ip.toBuffer('127.0.0.1');
// <Buffer 7f 00 00 01>
toString
(buff, offset?, length?): string

Converts a Buffer back to an IP address string.

ip.toString(
  Buffer.from('7f000001', 'hex')
); // '127.0.0.1'
toLong
(ip: string): number

IPv4 address to unsigned 32-bit integer.

ip.toLong('127.0.0.1');
// 2130706433
fromLong
(ipl: number): string

Unsigned 32-bit integer back to dotted-decimal.

ip.fromLong(2130706433);
// '127.0.0.1'
normalizeToLong
(addr: string): number

Normalizes any IPv4 notation to unsigned long. Returns -1 on invalid input.

ip.normalizeToLong('0x7f.0x0.0x0.1'); // 2130706433  (hex)
ip.normalizeToLong('0177.0.0.01');     // 2130706433  (octal)
ip.normalizeToLong('0x7f000001');      // 2130706433  (single hex)
ip.normalizeToLong('127.1');           // 2130706433  (compact)
ip.normalizeToLong('256.0.0.1');       // -1          (invalid)

Network Interface

address
(name?: string, family?: string | number): string
Node.js only

Returns an IP address from the current machine's network interfaces. Falls back to loopback() if no match found. Throws a descriptive error if called in a browser environment.

ip.address();             // first private IPv4, e.g. '192.168.1.42'
ip.address('public');     // first public IPv4
ip.address('private');    // first private IPv4
ip.address('eth0');       // first IPv4 on eth0
ip.address('eth0', 6);   // first IPv6 on eth0
loopback
(family?: string | number): string

Returns the loopback address for the given IP family.

ip.loopback();       // '127.0.0.1'
ip.loopback('ipv4'); // '127.0.0.1'
ip.loopback('ipv6'); // 'fe80::1'

Type declarations

import type { IPFamily, SubnetInfo } from 'node-ip-ts';

type IPFamily = 'ipv4' | 'ipv6';

interface SubnetInfo {
  networkAddress:   string;
  firstAddress:     string;
  lastAddress:      string;
  broadcastAddress: string;
  subnetMask:       string;
  subnetMaskLength: number;
  numHosts:         number;
  length:           number;
  contains(other: string): boolean;
}

Frequently asked questions

What is node-ip-ts?

node-ip-ts is a full TypeScript rewrite of the popular ip npm package, providing type-safe IP address utilities for Node.js with zero external dependencies, ES Module and CommonJS support.

Is node-ip-ts a drop-in replacement for the ip package?

Yes. All function names and behaviors are identical to the original ip package. Simply swap require('ip') to require('node-ip-ts').

Does node-ip-ts work in the browser?

All functions except address() work in both Node.js and browser/bundler environments. The address() function requires the Node.js os module and will throw a descriptive error if called in a browser.

Open to contributions

All changes must pass the test suite, include tests for new features, pass TypeScript strict mode, and maintain zero external runtime dependencies.

# Clone the repo
git clone https://github.com/denycode-dev/ip-ts.git
cd node-ip-ts

# Install dependencies
npm install

# Run tests
npm test

# Build
npm run build