IP range to CIDR calculator
Enter a first and last IPv4 address and get the fewest CIDR blocks that cover exactly that range: 192.168.1.13 to 192.168.1.20 becomes four blocks, with no address left out and none spilling into the neighbours. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Start ip
- 192.168.1.13
- End ip
- 192.168.1.20
- Start int
- 3,232,235,789
- End int
- 3,232,235,796
- Address count
- 8
- Cidr count
- 4
Firewalls, cloud security groups, and BGP advertisements almost never accept an arbitrary start-and-end IPv4 pair. They want CIDR prefixes: compact power-of-two blocks written as address slash prefix length. Turning a human range such as 192.168.1.13 through 192.168.1.20 into the smallest set of CIDRs that cover exactly those addresses—no missing hosts and no spillover into neighbors—is a classic network-engineering chore. This IP range to CIDR calculator does that conversion with a deterministic greedy algorithm: from the low end of the range it repeatedly emits the largest aligned block that still fits inside the remaining span. You get the flat list of CIDR strings, per-block first and last addresses, sizes, and the total host count.
What minimal exact CIDR coverage means
A CIDR block is a contiguous run of addresses whose length is a power of two and whose first address is aligned to that length: for prefix p the block size is two to the power of (32 minus p), and the network address must be divisible by that size. Covering a range with CIDRs is easy if you allow waste—just take a single oversized supernet—but waste is dangerous on allow-lists and wasteful on deny-lists.
Exact coverage means the union of the emitted blocks equals the original range set-theoretically: every address inside the range appears in exactly one block, and no address outside the range appears at all. Minimal means the fewest such blocks, which the standard greedy method achieves by always taking the largest legal block at the current left edge. For example the eight addresses from 192.168.1.13 to 192.168.1.20 become four prefixes: a host route for .13, a /31 for .14–.15, a /30 for .16–.19, and a host route for .20.
A single /29 would have reached from .16 to .23 and overshot; a single /28 would have been worse. The calculator never invents private-network assumptions: public, private, multicast, and loopback ranges are all treated as plain 32-bit integers, so the same logic works for RFC1918, CGNAT, and public space.
Where turning ranges into blocks saves time
Network and platform teams paste vendor-supplied start–end pairs into tickets and need CIDR form before they can open a change request. Cloud landing-zone modules accept CIDR lists only; converting spreadsheet columns of DHCP pools or partner interconnect ranges into Terraform locals is a common CI job. Prefer this capability when the search intent is range-to-prefix conversion; use a general subnet calculator when you already have a single CIDR and need mask, wildcard, or host-count details for that one block alone.
What you can do with it
Firewall and ACL authoring
Turn partner-provided start–end IPv4 ranges into the minimal CIDR list your firewall, security group, or router ACL syntax actually accepts.
Infrastructure-as-code and CI
Convert spreadsheet or CMDB address ranges into Terraform, Ansible, or policy-as-code CIDR arrays in a deterministic pipeline step.
Threat intel and SOAR enrichment
Normalize indicator ranges from tickets into exact CIDR sets for match conditions without overshooting into benign neighbors.
FAQ
How is this different from a subnet calculator?
A subnet calculator usually starts from one CIDR and reports mask, hosts, and bounds. This tool starts from an arbitrary start–end pair and produces the minimal multi-CIDR cover.
Why does one range turn into several CIDR blocks?
Each block must hold a power-of-two number of addresses and start on a matching boundary. The eight addresses from 192.168.1.13 to 192.168.1.20 fit in no single block, so they become four: .13 alone, .14 to .15, .16 to .19, and .20 alone.
Why not cover the range with one bigger block?
Because it would spill into the neighbours. A /29 starting at .16 reaches .23, past the end of the range. On an allow-list that would open addresses you never meant to let in, so only exact blocks come out.
What happens if I swap the start and end addresses?
The range is refused instead of being quietly reversed. The start must be lower than or equal to the end, because a silent swap would hide a copy-and-paste mistake in your list.
How many blocks can an IPv4 range need at most?
Never more than 32. The whole address space, from 0.0.0.0 to 255.255.255.255, even collapses into a single block, 0.0.0.0/0, so the result always stays short.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev/ip-range-to-cidr \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"start_ip":"192.168.1.13","end_ip":"192.168.1.20"}'const res = await fetch("https://api.kit.forhosting.com/dev/ip-range-to-cidr", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"start_ip": "192.168.1.13",
"end_ip": "192.168.1.20"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/ip-range-to-cidr",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"start_ip": "192.168.1.13",
"end_ip": "192.168.1.20"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/ip-range-to-cidr", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"start_ip":"192.168.1.13","end_ip":"192.168.1.20"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"start_ip":"192.168.1.13","end_ip":"192.168.1.20"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/ip-range-to-cidr", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"start_ip": "192.168.1.13",
"end_ip": "192.168.1.20"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.ip_range_to_cidr",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
What minimal exact CIDR coverage means
An inclusive IPv4 range is every address from start_ip through end_ip counted as 32-bit integers.
Input contract, response shape, and validation
The greedy loop emits at most thirty-two blocks for any IPv4 range, so response size stays tiny even for 0.0.0.0 through 255.255.255.255, which collapses to the single prefix 0.0.0.0/0. Pair the cidrs list with your firewall dialect—AWS security-group CIDRs, iptables, nftables, Cisco ACL object-groups, or edge CDN IP allow-lists—without further math on your side. POST a JSON body with two required strings: start_ip and end_ip, each a strict dotted-quad IPv4 address with four decimal octets from 0 to 255 and no leading zeros (so 192.168.1.1 is valid and 192.168.01.1 is rejected). Whitespace around the string is trimmed. start_ip must be less than or equal to end_ip; reversed ranges fail with invalid_input rather than silently swapping ends, because silent swaps hide copy-paste bugs in automation. On success the body echoes the normalized start_ip and end_ip, their unsigned integer forms start_int and end_int, the inclusive address_count, the cidr_count, a flat cidrs array of strings such as 10.0.0.0/8, and a blocks array of objects each carrying cidr, prefix, network, first_ip, last_ip, and size. Missing fields, non-string values, malformed octets, out-of-range octets, and start greater than end all raise invalid_input and are not billed.
Where an IP range to CIDR API earns its keep
SIEM and SOAR playbooks that expand threat-intel ranges into match conditions benefit from a pure parse endpoint with no outbound network of its own.
Technical questions
How do I convert an IPv4 range to CIDR blocks?
Send start_ip and end_ip as dotted-quad strings with start ≤ end. The API returns the minimal exact list in cidrs plus per-block network, first_ip, last_ip, prefix, and size.
Does the calculator cover the range exactly?
Yes. The greedy algorithm never overshoots end_ip and never skips addresses inside the inclusive range, so the union of blocks equals the original range.
What if start_ip is greater than end_ip?
The task fails with invalid_input. Ends are not swapped automatically so automation bugs stay visible; fix the order and retry.
What does the IP range to CIDR calculator cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.