IPv6 prefix checker
The IPv6 prefix checker answers a precise routing and access-control question: does this address belong to that CIDR block?
Run — free
Enter an IPv6 address and a prefix such as 2001:db8:1234::/48. The checker compares the high-order network bits, returns a clear true or false result, and shows the normalized network plus its first and last addresses. Compressed, expanded, and IPv4-embedded IPv6 notation are handled with exact 128-bit arithmetic, so even boundary addresses and unusual prefix lengths are evaluated without rounding.
What IPv6 prefix membership means
An IPv6 prefix divides a 128-bit address into network bits and host bits. The number after the slash states how many high-order bits identify the network. For example, a /48 fixes the first 48 bits while leaving the remaining 80 bits available inside that block. An address belongs to the prefix when all fixed network bits match; the textual spelling is irrelevant. That distinction matters because IPv6 allows omitted leading zeroes, compressed runs written as ::, and different-looking strings that represent exactly the same value. This checker parses both values into exact integers, builds the mask for the requested prefix length, and compares only the bits that define membership. It also normalizes the supplied prefix to its true network boundary. If someone enters a host address such as 2001:db8:1234:99::1/48, the compared network is still 2001:db8:1234::/48. The result therefore reflects CIDR semantics instead of relying on fragile string prefixes or colon-group comparisons.
Reading the Boolean result and network range
The primary result is in_prefix, a Boolean that can be used directly in code, validation rules, routing checks, or audit reports. The response also returns the canonical address and canonical prefix so you can see exactly what was compared. The first_address and last_address fields describe the inclusive limits of the network, while matched_network_range presents those same limits as a compact readable range. These fields are returned for both true and false results: when the answer is false, the range explains the block that the address failed to enter. Boundary behavior is exact. The first and last addresses of a prefix both count as members because IPv6 does not reserve a broadcast address. A /128 contains one address, so its first and last values are identical. A /0 covers every IPv6 address. No floating-point values are involved; all masking and range calculations use exact 128-bit integer operations, including ranges far larger than JavaScript's safe integer limit.
Valid input and common mistakes
Provide address as a bare IPv6 address and prefix as an IPv6 network followed by a slash length from 0 through 128. Standard compressed notation such as 2001:db8::1, fully expanded notation, and IPv4-embedded endings such as ::ffff:192.0.2.1 are accepted. The checker deliberately rejects ambiguous or out-of-scope input. The address field cannot include its own slash length, the prefix must include one, IPv4-only values are not treated as IPv6, and zone identifiers such as %eth0 are rejected because they identify an interface context rather than part of the 128-bit address. Invalid hexadecimal groups, multiple :: compressions, groups longer than four digits, and prefix lengths outside the allowed range produce an input error instead of a guessed answer. This strictness is useful in automation: malformed configuration fails visibly before it can become an incorrect allow-list decision. For security-sensitive authorization, remember that membership is only one fact; apply your separate identity, trust, and policy checks as well.
What you can do with it
Validate an IPv6 allow list
Check whether a client or service address is contained by an approved CIDR block before applying a network policy.
Debug routing configuration
Confirm that an address falls inside the route prefix you expect and inspect the exact normalized boundaries when it does not.
Test IP address management data
Verify imported addresses against assigned IPv6 prefixes and flag records that were placed in the wrong network.
FAQ
How much does one check cost?
Each API request costs $0.002. The same deterministic check is also available free in the browser.
Does the checker accept compressed IPv6 addresses?
Yes. Standard :: compression and omitted leading zeroes are accepted, then the address is returned in canonical lowercase form.
Are the first and last addresses included?
Yes. The reported range is inclusive, and IPv6 has no reserved broadcast address at the end of a prefix.
What happens if the prefix contains host bits?
It is normalized to the actual network boundary before comparison, and the normalized CIDR is returned in the result.
Can I check an IPv4 address?
No. This capability is specifically for IPv6, although valid IPv4-embedded IPv6 notation is supported.
Does a false result still include the range?
Yes. The response shows the inclusive network range that was tested so you can see why the address falls outside it.
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/ipv6-in-prefix \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"address":"2001:db8:1234::42","prefix":"2001:db8:1234::/48"}'const res = await fetch("https://api.kit.forhosting.com/dev/ipv6-in-prefix", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"address": "2001:db8:1234::42",
"prefix": "2001:db8:1234::/48"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/ipv6-in-prefix",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"address": "2001:db8:1234::42",
"prefix": "2001:db8:1234::/48"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/ipv6-in-prefix", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"address":"2001:db8:1234::42","prefix":"2001:db8:1234::/48"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"address":"2001:db8:1234::42","prefix":"2001:db8:1234::/48"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/ipv6-in-prefix", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"address": "2001:db8:1234::42",
"prefix": "2001:db8:1234::/48"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.ipv6_in_prefix",
"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. |