Everything happens locally in your browser. Nothing you type here is sent anywhere, logged, or stored, it disappears the moment you close the tab.
Network Address—
Broadcast Address—
Subnet Mask—
Wildcard Mask—
First Usable Host—
Last Usable Host—
Usable Hosts—
Total Addresses—
Reading CIDR Notation
The number after the slash is how many bits of the address are fixed as the network portion, everything left over is host space. A smaller number after the slash means fewer fixed bits and more usable addresses, a larger number means the opposite: more networks, fewer hosts each. It's the same information a dotted-decimal subnet mask carries, just written as a single number instead of four octets.
Network, Broadcast, and the Usable Range
The network address is the first address in the block and identifies the subnet itself, it's never assigned to a device. The broadcast address is the last one, reserved for sending to every host on that subnet at once. Everything between those two is what's actually usable, which is why a /24 has 256 total addresses but only 254 you can assign. Two special cases break that pattern: a /31 has no network or broadcast waste at all, both addresses are usable, which is exactly why point-to-point links between routers often use it. A /32 is a single address with no room for anything else, a host route.
Common Prefixes Worth Memorizing
A /24 is the default for most home and small office networks: 256 addresses, 254 usable, subnet mask 255.255.255.0. A /16 is a full class-B-sized block, 65,536 addresses, the size of most private 172.16.x.x or a large 10.x.x.x allocation. A /30 is the smallest practical subnet with a real network and broadcast address, 4 total, 2 usable, occasionally still used for point-to-point links before /31 became common. Knowing these few by memory covers most day-to-day networking without needing to reach for a calculator at all, this tool is for the ones that don't fit a pattern you already know.
Where This Actually Matters
Setting up a home lab network and need to know if two subnets overlap. Configuring a firewall rule and want to be sure the range you're allowing is exactly the range you mean, not accidentally wider. Reading a router's DHCP pool settings and translating the mask back into how many devices it can actually hand addresses to. This calculator exists for the moment you're doing one of those things and want the answer to be exact, not approximate.
Copy the Code
Plain HTML, CSS, and JavaScript, no dependencies, no build step, nothing phoned home. Comments walk through what each block is doing, so it's easy to adapt rather than just paste and forget.
<!-- Subnet / CIDR Calculator -- copy this whole block into any HTML page. -->
<!-- No build step, no dependencies -- plain HTML, CSS, and JS. -->
<!-- Everything runs locally: nothing is ever sent anywhere. -->
<div id="cidr-calculator">
<div class="cidr-field">
<input type="text" id="cidrInput" placeholder="192.168.1.0/24" autocomplete="off" spellcheck="false" value="192.168.1.0/24">
</div>
<p id="cidrError"></p>
<div id="cidrResults">
<div><span>Network Address</span> <span id="cidrNetwork">—</span></div>
<div><span>Broadcast Address</span> <span id="cidrBroadcast">—</span></div>
<div><span>Subnet Mask</span> <span id="cidrMask">—</span></div>
<div><span>Wildcard Mask</span> <span id="cidrWildcard">—</span></div>
<div><span>First Usable Host</span> <span id="cidrFirstHost">—</span></div>
<div><span>Last Usable Host</span> <span id="cidrLastHost">—</span></div>
<div><span>Usable Hosts</span> <span id="cidrUsableHosts">—</span></div>
<div><span>Total Addresses</span> <span id="cidrTotalAddresses">—</span></div>
</div>
</div>
<style>
/* Minimal styling -- restyle freely to match your own site. */
#cidr-calculator { font-family: sans-serif; max-width: 480px; }
#cidr-calculator input { width: 100%; padding: 8px 10px; box-sizing: border-box; text-align: center; }
#cidr-calculator p { min-height: 1.2em; color: #c0392b; font-size: 0.85rem; }
#cidrResults { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; opacity: 0.35; transition: opacity 0.15s ease; }
#cidrResults.visible { opacity: 1; }
#cidrResults > div { padding: 10px; background: #f4f4f4; border-radius: 6px; }
#cidrResults span:first-child { display: block; font-size: 0.7rem; text-transform: uppercase; opacity: 0.6; margin-bottom: 4px; }
#cidrResults span:last-child { display: block; font-weight: 600; }
</style>
<script>
(function () {
var input = document.getElementById('cidrInput');
var error = document.getElementById('cidrError');
var results = document.getElementById('cidrResults');
var fields = {
network: document.getElementById('cidrNetwork'),
broadcast: document.getElementById('cidrBroadcast'),
mask: document.getElementById('cidrMask'),
wildcard: document.getElementById('cidrWildcard'),
firstHost: document.getElementById('cidrFirstHost'),
lastHost: document.getElementById('cidrLastHost'),
usableHosts: document.getElementById('cidrUsableHosts'),
totalAddresses: document.getElementById('cidrTotalAddresses')
};
// Converts a dotted-decimal IP into an unsigned 32-bit integer.
function ipToInt(ip) {
return ip.split('.').reduce(function (acc, octet) {
return (acc << 8) + Number(octet);
}, 0) >>> 0;
}
function intToIp(int) {
return [24, 16, 8, 0].map(function (shift) {
return (int >>> shift) & 255;
}).join('.');
}
function parseInput(value) {
var trimmed = value.trim();
var match = trimmed.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/);
if (!match) return null;
var octets = match.slice(1, 5).map(Number);
var prefix = Number(match[5]);
for (var i = 0; i < octets.length; i++) {
if (octets[i] < 0 || octets[i] > 255) return null;
}
if (prefix < 0 || prefix > 32) return null;
return { ip: octets.join('.'), prefix: prefix };
}
function calculate(ip, prefix) {
var ipInt = ipToInt(ip);
var maskInt = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;
var wildcardInt = (~maskInt) >>> 0;
var networkInt = (ipInt & maskInt) >>> 0;
var broadcastInt = (networkInt | wildcardInt) >>> 0;
var totalAddresses = Math.pow(2, 32 - prefix);
// /32 is a single host route, /31 is a point-to-point link (RFC 3021)
// where both addresses are usable. Everything else follows the normal
// network/broadcast-reserved rule.
var firstHost, lastHost, usableHosts;
if (prefix === 32) {
firstHost = networkInt; lastHost = networkInt; usableHosts = 1;
} else if (prefix === 31) {
firstHost = networkInt; lastHost = broadcastInt; usableHosts = 2;
} else {
firstHost = networkInt + 1; lastHost = broadcastInt - 1; usableHosts = totalAddresses - 2;
}
return {
network: intToIp(networkInt),
broadcast: intToIp(broadcastInt),
mask: intToIp(maskInt),
wildcard: intToIp(wildcardInt),
firstHost: intToIp(firstHost >>> 0),
lastHost: intToIp(lastHost >>> 0),
usableHosts: usableHosts.toLocaleString(),
totalAddresses: totalAddresses.toLocaleString()
};
}
function render() {
var parsed = parseInput(input.value);
if (!parsed) {
error.textContent = input.value.trim() ? 'Enter a valid address like 192.168.1.0/24.' : '';
results.classList.remove('visible');
return;
}
error.textContent = '';
var result = calculate(parsed.ip, parsed.prefix);
Object.keys(fields).forEach(function (key) {
if (fields[key]) fields[key].textContent = result[key];
});
results.classList.add('visible');
}
input.addEventListener('input', render);
render();
})();
</script>