ip and public-ip handle network addresses but solve different problems for developers. ip is a utility library for validating, converting, and calculating IP subnets locally without network access. public-ip is a network tool that queries external DNS or HTTPS services to discover your server's public-facing address.
Both ip and public-ip deal with network addresses, but they serve distinct roles in a Node.js architecture. ip focuses on local manipulation and validation of IP strings, while public-ip focuses on network discovery to find your outward-facing address. Let's compare how they tackle common engineering tasks.
ip retrieves the address assigned to a local network interface on the machine.
192.168.1.5) if behind a router.// ip: Get local interface address
const ip = require('ip');
const localAddress = ip.address();
// Returns: "192.168.1.5" (example)
public-ip queries external services to find what the internet sees.
api.ipify.org.203.0.113.10) even behind NAT.// public-ip: Get external public address
import publicIp from 'public-ip';
const publicAddress = await publicIp();
// Returns: "203.0.113.10" (example)
ip provides methods to validate formats and check ranges.
// ip: Validate and check range
const ip = require('ip');
const isValid = ip.isV4Format('192.168.1.1');
const isPrivate = ip.isPrivate('192.168.1.1');
// isValid: true, isPrivate: true
public-ip returns a raw string without validation tools.
ip or another library to validate the result.// public-ip: No built-in validation
import publicIp from 'public-ip';
const address = await publicIp();
// You must use another library to check if 'address' is valid
ip is written in pure JavaScript with no system dependencies.
// ip: Works in browser or Node
const ip = require('ip');
// Can be bundled with Webpack or Vite for client use
const isLoopback = ip.isLoopback('127.0.0.1');
public-ip requires Node.js network modules.
dns and https modules unavailable in browsers.// public-ip: Node.js only
import publicIp from 'public-ip';
// Will fail in browser environment due to missing 'dns' module
const address = await publicIp();
ip operates entirely offline with no external calls.
// ip: Deterministic and offline
const ip = require('ip');
// Always returns immediately without network latency
const subnet = ip.subnet('192.168.1.1', '255.255.255.0');
public-ip depends on external APIs being reachable.
api.ipify.org is down, your promise rejects.// public-ip: Network dependent
import publicIp from 'public-ip';
try {
const address = await publicIp();
} catch (error) {
// Handle network failure or API downtime
console.error('Failed to get public IP');
}
ip had a known ReDoS vulnerability in older versions.
// ip: Security patch required
// Ensure package.json specifies "ip": "^1.1.6" or higher
const ip = require('ip');
// Validating untrusted input is now safe on patched versions
public-ip sends your IP to third-party services.
// public-ip: Privacy consideration
import publicIp from 'public-ip';
// Your IP is sent to external APIs (dns/https)
const address = await publicIp({ onlyHttps: true });
| Feature | ip | public-ip |
|---|---|---|
| Primary Goal | 🧮 Validate & Calculate | 📡 Discover External IP |
| Network Access | ❌ None (Offline) | ✅ Required (DNS/HTTPS) |
| Environment | 🌍 Browser & Node.js | 🖥️ Node.js Only |
| Reliability | ⚡ Deterministic | ⚠️ Depends on APIs |
| Privacy | 🔒 Local Processing | 📤 Sends IP Externally |
ip is like a calculator 🧮 — it helps you compute and verify network data locally. It is essential for security middleware, subnet planning, and input validation where speed and reliability matter.
public-ip is like a phone book 📞 — it looks up your public identity from the outside world. It is useful for registration scripts, logging, and dynamic firewall updates where knowing your external IP is critical.
Final Thought: These packages are not competitors but companions. In a robust Node.js service, you might use public-ip at startup to register your server, and ip throughout your request pipeline to validate incoming connections. Choose based on whether you need to calculate an address or discover one.
Choose ip when you need to validate user input, calculate subnet masks, or check if an address is private locally. It works offline and is deterministic, making it safe for critical logic without network dependencies. This is ideal for server-side validation middleware or network configuration tools.
Choose public-ip when your server needs to know its own external IP for logging or firewall allowlists. It requires internet access and relies on third-party services, so handle errors gracefully. This is best for startup scripts that need to register the server's location with an external service.
IP address utilities for node.js
npm install ip
git clone https://github.com/indutny/node-ip.git
Get your ip address, compare ip addresses, validate ip addresses, etc.
var ip = require('ip');
ip.address() // my ip address
ip.isEqual('::1', '::0:1'); // true
ip.toBuffer('127.0.0.1') // Buffer([127, 0, 0, 1])
ip.toString(new Buffer([127, 0, 0, 1])) // 127.0.0.1
ip.fromPrefixLen(24) // 255.255.255.0
ip.mask('192.168.1.134', '255.255.255.0') // 192.168.1.0
ip.cidr('192.168.1.134/26') // 192.168.1.128
ip.not('255.255.255.0') // 0.0.0.255
ip.or('192.168.1.134', '0.0.0.255') // 192.168.1.255
ip.isPrivate('127.0.0.1') // true
ip.isV4Format('127.0.0.1'); // true
ip.isV6Format('::ffff:127.0.0.1'); // true
// operate on buffers in-place
var buf = new Buffer(128);
var offset = 64;
ip.toBuffer('127.0.0.1', buf, offset); // [127, 0, 0, 1] at offset 64
ip.toString(buf, offset, 4); // '127.0.0.1'
// subnet information
ip.subnet('192.168.1.134', '255.255.255.192')
// { networkAddress: '192.168.1.128',
// firstAddress: '192.168.1.129',
// lastAddress: '192.168.1.190',
// broadcastAddress: '192.168.1.191',
// subnetMask: '255.255.255.192',
// subnetMaskLength: 26,
// numHosts: 62,
// length: 64,
// contains: function(addr){...} }
ip.cidrSubnet('192.168.1.134/26')
// Same as previous.
// range checking
ip.cidrSubnet('192.168.1.134/26').contains('192.168.1.190') // true
// ipv4 long conversion
ip.toLong('127.0.0.1'); // 2130706433
ip.fromLong(2130706433); // '127.0.0.1'
This software is licensed under the MIT License.
Copyright Fedor Indutny, 2012.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.