# IP Address Inspector

> Canonical form, special-purpose ranges, embedded IPv4 and reachability of any IPv4 or IPv6 address.

Category: Inspect & Identify · Page: https://util.caruana.me/tools/ip/

## API, MCP and A2A

### Inspect an IP address (`ip_inspect`)

`GET|POST https://util.caruana.me/api/ip/inspect` · MCP tool `ip_inspect` · A2A skill `ip_inspect` · [reference](https://util.caruana.me/reference/ip_inspect/)

Parses an IPv4 or IPv6 address in any spelling and returns its canonical form (RFC 5952 for IPv6), the full expanded form and integer value, any IPv4 address embedded in an IPv6 address (IPv4-mapped, IPv4-compatible, IPv4-translated, NAT64 `64:ff9b::/96` and `64:ff9b:1::/48`, 6to4, Teredo), every range it falls in from the IANA IPv4 and IPv6 Special-Purpose Address Registries (with their source, destination, forwardable, globally-reachable and reserved columns), and whether it is globally reachable. An embedded IPv4 address is checked too, so `::ffff:a00:1` is reported as private-use `10.0.0.1`. Non-standard IPv4 spellings that browsers and `inet_aton` accept (`127.1`, `0x7f.0.0.1`, `0177.0.0.1`, `2130706433`) are read the way they are and flagged. A `/prefix` adds the network, and `cidrs` tests membership. Nothing is resolved or contacted.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `address` | string (≤ 104 chars) | yes | An IPv4 or IPv6 address in any spelling. Optional: `[brackets]`, an IPv6 zone ID (`fe80::1%eth0`), or a `/prefix` to describe the network as well. |
| `cidrs` | list of strings | no | Comma-separated CIDRs (IPv4 or IPv6, up to 100) to test the address against, e.g. `10.0.0.0/8,fc00::/7`. An IPv6 address also matches an IPv4 CIDR through its embedded IPv4 address. |

Privacy: The server receives the address (and any CIDRs), analyses it in memory, and returns the result. Your input is not stored or logged; only the per-call metadata row (operation, time, status, sizes) is recorded. The address is never resolved or contacted.


## User guide

The tool sits in a window that works like a desktop app: menus on the top row and the **full-screen** icon at its right (**Esc** leaves full screen). The set-up options described below are in **Settings → Options…**, an overlay. To keep the options in view instead, choose **View → Inline config**; the page remembers that choice. **Help → Keyboard shortcuts…** lists the keys.

1. **Paste an address** in any spelling: `10.0.0.1`, `::ffff:a00:1`, `[2001:db8::1]`, `fe80::1%eth0`, even `0x7f.1`. Add a `/prefix` (`192.168.1.77/24`) to see the network as well.
2. Optionally, in **Settings → Options…**, list **CIDRs** to test it against (one per line or comma-separated), such as the blocks your firewall or SSRF filter refuses.
3. Read the cards:
   - **Overview:** the canonical form (with **Copy**), the full expanded IPv6 form, any zone ID, the IPv4 address embedded in an IPv6 one, and the integer value. The badge says whether the address is globally reachable.
   - **Special-purpose ranges:** every IANA registry block the address falls in, including blocks matched by its embedded IPv4 address.
   - **Network** and **CIDR membership**, when asked for.
   - **Notes:** non-standard spellings, deprecated forms, host bits set.

**Why it matters.** An IP address can be written many ways, and code that checks the text instead of the parsed address gets fooled. `::ffff:a00:1` is `10.0.0.1`. `0x7f.1` and `2130706433` are both `127.0.0.1` to a browser or `curl`. `64:ff9b::a00:1` reaches `10.0.0.1` through a NAT64 gateway. An SSRF filter, firewall rule or allow-list has to judge the address these resolve to; this tool shows it.

## Specification

**Parsing.**

- **IPv6:** RFC 4291 §2.2 text forms: up to eight 16-bit hex groups, at most one `::`, optionally ending in a dotted IPv4 address. Upper and lower case are accepted. Square brackets (`[::1]`) are accepted; a port (`[::1]:443`) is refused. A zone ID after `%` (RFC 4007 §11) is kept separately and does not change the address.
- **IPv4:** a strict dotted quad (four decimal parts 0–255, no leading zeros). The legacy forms that `inet_aton(3)` and the WHATWG URL parser (browsers, `curl`) accept are also read the way those parsers read them, with a note: one to four parts, each decimal, octal (leading `0`) or hex (`0x`), the last part filling the remaining bytes (`127.1`, `0177.0.0.1`, `0x7f000001`, `2130706433`). A leading zero means octal there (`010.0.0.1` is `8.0.0.1`); strict parsers reject such addresses or read them as decimal. One trailing dot is ignored, as URL parsers ignore it.
- Up to 100 characters. A `/prefix` (0–32 or 0–128) may follow the address.

**Canonical form.** IPv4: dotted decimal. IPv6: RFC 5952: lowercase hex, no leading zeros, the longest run of two or more zero groups replaced by `::` (the first if two runs are equally long; a single zero group is never compressed). The last 32 bits are written as a dotted IPv4 address for IPv4-mapped, IPv4-compatible and IPv4-translated addresses (RFC 5952 §5) and for the well-known NAT64 prefix `64:ff9b::/96` (RFC 6052 §2.4). `::2` stays `::2` rather than `::0.0.0.2`. `expanded` always has eight four-digit groups; `integer` is the unsigned value in decimal.

**Embedded IPv4.** The IPv4 address carried in an IPv6 address, and how:

| `embedding`       | Block                     | Where the IPv4 address is                           | Defined in                     |
| ----------------- | ------------------------- | --------------------------------------------------- | ------------------------------ |
| `ipv4-mapped`     | `::ffff:0:0/96`           | last 32 bits                                        | RFC 4291 §2.5.5.2              |
| `ipv4-compatible` | `::/96` (not `::`, `::1`) | last 32 bits                                        | RFC 4291 §2.5.5.1 (deprecated) |
| `ipv4-translated` | `::ffff:0:0:0/96`         | last 32 bits                                        | RFC 2765 (obsolete SIIT)       |
| `nat64`           | `64:ff9b::/96`            | last 32 bits                                        | RFC 6052                       |
| `nat64`           | `64:ff9b:1::/48`          | bits 48–63 and 72–87 (the `/48` layout)             | RFC 8215, RFC 6052 §2.2        |
| `6to4`            | `2002::/16`               | bits 16–47                                          | RFC 3056                       |
| `teredo`          | `2001::/32`               | the client's address, inverted, in the last 32 bits | RFC 4380                       |

For Teredo, the server address (bits 32–63) and the client's UDP port are given in the notes.

**Ranges.** Every block the address falls in, least specific first, from the IANA IPv4 and IPv6 Special-Purpose Address Registries (RFC 6890, updated by RFC 8190) with their columns: `source`, `destination`, `forwardable`, `globally_reachable` and `reserved_by_protocol` (`null` where the registry says N/A). Multicast (`224.0.0.0/4`, RFC 5771; `ff00::/8`) and the deprecated site-local block (`fec0::/10`, RFC 3879) come from the address-space registries and have no columns. A block matched by the embedded IPv4 address has `via: "embedded_ipv4"`.

**Global reachability.**

1. The most specific special-purpose block with a value decides (RFC 8190 §3): `192.0.0.9` is reachable although `192.0.0.0/24` is not.
2. Where that block says N/A (Teredo, 6to4), the embedded IPv4 address decides.
3. An address in no special-purpose block is reachable if it is IPv4 unicast or IPv6 global unicast (`2000::/3`). Other IPv6 space is reserved, so not reachable. Multicast depends on its scope, so it is `null`.
4. Whatever the IPv6 block says, a non-reachable embedded IPv4 address makes the result `false`: `64:ff9b::a00:1` reaches the private `10.0.0.1` through a NAT64 gateway.

**CIDR membership.** Each `cidrs` entry (a strict address plus `/prefix`; host bits are ignored) reports `contains`. An IPv6 address also matches an IPv4 CIDR through its embedded IPv4 address (`via: "embedded_ipv4"`), so `::ffff:10.1.2.3` is in `10.0.0.0/8`. At most 100 CIDRs.

**Not covered.** Host names are not resolved: use the address a name resolves to. IPv6 scope beyond link-local and multicast, and the IPv4 and IPv6 multicast sub-registries, are not analysed.
