API reference

Inspect an IP address

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

GETPOST/api/ip/inspectMCP tool 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.

Browser version (runs locally): IP Address Inspector.

Try it

Credentials
Remember these credentials

Not saved: you will paste them again next time.

No credentials yet? Get a client ID and secret. They are sent only to this site, in an Authorization: Basic header.

POST /api/ip/inspect with a JSON body

Parameters

ParameterTypeDefaultDescription
addressrequiredstring (≤ 104 chars)—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.
cidrslist of strings—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.

Also accepted on every endpoint: format (json | text). Parameters may come from the query string, a JSON object body, an urlencoded or multipart form, or (for input) a text/plain body.

Global parameters
ParameterTypeDefaultDescription
formatjson | textjsonjson returns the documented object. text returns only the primary value as text/plain (see "Text output").

Response 200 application/json

FieldTypeDescription
versioninteger4 or 6.
inputstringThe input as given.
canonicalstringCanonical text form: dotted decimal for IPv4; RFC 5952 for IPv6 (lowercase, shortest, embedded IPv4 in dotted form where RFC 5952/6052 recommend it).
expandedstringIPv6: all eight groups, four hex digits each. IPv4: dotted decimal.
zonestring | nullIPv6 zone ID (the part after %), if any.
integerstringThe address as an unsigned integer, in decimal.
embedded_ipv4string | nullAn IPv4 address carried inside the IPv6 address.
embeddingone of (by kind)How the IPv4 address is embedded.
embedding (kind = "undefined")variant
embedding (kind = "undefined")variant
rangesarray of objectEvery special-purpose range matched, least specific first.
ranges[].cidrstringThe registry block, e.g. 10.0.0.0/8.
ranges[].namestringThe registry's name for it, e.g. Private-Use.
ranges[].rfcstringWhere it is defined.
ranges[].registry"ipv4-special-purpose" | "ipv6-special-purpose" | "ipv4-multicast" | "ipv6-address-space"Which IANA registry it comes from.
ranges[].sourceone of (by kind)Valid as a source address (null: N/A or not in a special-purpose registry).
ranges[].source (kind = "undefined")variant
ranges[].source (kind = "undefined")variant
ranges[].destinationone of (by kind)Valid as a destination address.
ranges[].destination (kind = "undefined")variant
ranges[].destination (kind = "undefined")variant
ranges[].forwardableone of (by kind)Routers may forward it.
ranges[].forwardable (kind = "undefined")variant
ranges[].forwardable (kind = "undefined")variant
ranges[].globally_reachableone of (by kind)Reachable on the global internet, per the registry.
ranges[].globally_reachable (kind = "undefined")variant
ranges[].globally_reachable (kind = "undefined")variant
ranges[].reserved_by_protocolone of (by kind)Reserved by a protocol specification.
ranges[].reserved_by_protocol (kind = "undefined")variant
ranges[].reserved_by_protocol (kind = "undefined")variant
ranges[].via"address" | "embedded_ipv4"Matched by the address itself, or by the IPv4 address embedded in it.
globally_reachableone of (by kind)Whether the address is globally reachable; false if an embedded IPv4 address is not. null when it depends on scope (multicast).
globally_reachable (kind = "undefined")variant
globally_reachable (kind = "undefined")variant
networkone of (by kind)With a /prefix: the network. Otherwise null.
network (kind = "undefined")variant
network.cidrstringThe network, host bits cleared.
network.prefixintegerPrefix length.
network.firststringFirst address.
network.laststringLast address (the broadcast address for IPv4).
network.sizestringNumber of addresses, in decimal.
network.netmaskstring | nullIPv4 dotted netmask.
network (kind = "undefined")variant
cidr_matchesarray of objectOne entry per cidrs value, in order.
cidr_matches[].cidrstringThe CIDR as given.
cidr_matches[].containsbooleanWhether the address (or its embedded IPv4) is inside it.
cidr_matches[].viaone of (by kind)What matched.
cidr_matches[].via (kind = "undefined")variant
cidr_matches[].via (kind = "undefined")variant
notesarray of stringNon-standard spellings, deprecated forms, host bits set.

Text output (format=text, text/plain): The canonical form.

Errors

Errors are JSON: {"error": "<message>", "code": "<code>", "param": "<name>"?}.

StatusCodeWhen
422unprocessable_inputaddress is not an IPv4 or IPv6 address (the message says why), has a port, a zone ID on IPv4, or a prefix longer than the address.
400invalid_parameterA cidrs value is not a valid CIDR, or there are more than 100.
400missing_parameterA required parameter is absent.
400unknown_parameterA parameter name is not in the table above (typos are rejected, not ignored).
413payload_too_largeThe request body exceeds 1 MiB.
405method_not_allowedA method other than GET, POST or OPTIONS.

Behaviour

  • Idempotent: the same arguments always return the same result.
  • Requires a client ID and secret (authentication). Each call is recorded as one metadata row against your client ID; inputs and outputs are never stored or logged. Responses carry cache-control: no-store.
  • CORS: any origin may call this endpoint from a browser, using your credentials.

Examples

Responses below were produced by running each request through this code at build time. Long strings are shortened.

IPv4-mapped IPv6 written in hex: a private address in disguise

curl 'https://util.caruana.me/api/ip/inspect?address=%3A%3Affff%3Aa00%3A1'

Response 200

{
  "version": 6,
  "input": "::ffff:a00:1",
  "canonical": "::ffff:10.0.0.1",
  "expanded": "0000:0000:0000:0000:0000:ffff:0a00:0001",
  "zone": null,
  "integer": "281470849515521",
  "embedded_ipv4": "10.0.0.1",
  "embedding": "ipv4-mapped",
  "ranges": [
    {
      "cidr": "::ffff:0:0/96",
      "name": "IPv4-mapped Address",
      "rfc": "RFC 4291",
      "registry": "ipv6-special-purpose",
      "source": false,
      "destination": false,
      "forwardable": false,
      "globally_reachable": false,
      "reserved_by_protocol": true,
      "via": "address"
    },
    {
      "cidr": "10.0.0.0/8",
      "name": "Private-Use",
      "rfc": "RFC 1918",
      "registry": "ipv4-special-purpose",
      "source": true,
      "destination": true,
      "forwardable": true,
      "globally_reachable": false,
      "reserved_by_protocol": false,
      "via": "embedded_ipv4"
    }
  ],
  "globally_reachable": false,
  "network": null,
  "cidr_matches": [],
  "notes": []
}
Same call as an MCP tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ip_inspect",
    "arguments": {
      "address": "::ffff:a00:1"
    }
  }
}

Legacy IPv4 shorthand, as an SSRF payload would write it

curl 'https://util.caruana.me/api/ip/inspect?address=0x7f.1&cidrs=127.0.0.0%2F8%2C10.0.0.0%2F8'

Response 200

{
  "version": 4,
  "input": "0x7f.1",
  "canonical": "127.0.0.1",
  "expanded": "127.0.0.1",
  "zone": null,
  "integer": "2130706433",
  "embedded_ipv4": null,
  "embedding": null,
  "ranges": [
    {
      "cidr": "127.0.0.0/8",
      "name": "Loopback",
      "rfc": "RFC 1122 §3.2.1.3",
      "registry": "ipv4-special-purpose",
      "source": false,
      "destination": false,
      "forwardable": false,
      "globally_reachable": false,
      "reserved_by_protocol": true,
      "via": "address"
    }
  ],
  "globally_reachable": false,
  "network": null,
  "cidr_matches": [
    {
      "cidr": "127.0.0.0/8",
      "contains": true,
      "via": "address"
    },
    {
      "cidr": "10.0.0.0/8",
      "contains": false,
      "via": null
    }
  ],
  "notes": [
    "\"0x7f.1\" is a non-standard IPv4 spelling. inet_aton(3), browsers, curl and other WHATWG URL parsers read it as 127.0.0.1… (110 more characters)"
  ]
}
Same call as an MCP tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ip_inspect",
    "arguments": {
      "address": "0x7f.1",
      "cidrs": [
        "127.0.0.0/8",
        "10.0.0.0/8"
      ]
    }
  }
}

NAT64 address with a network prefix

curl 'https://util.caruana.me/api/ip/inspect?address=64%3Aff9b%3A%3Ac000%3A221%2F96'

Response 200

{
  "version": 6,
  "input": "64:ff9b::c000:221/96",
  "canonical": "64:ff9b::192.0.2.33",
  "expanded": "0064:ff9b:0000:0000:0000:0000:c000:0221",
  "zone": null,
  "integer": "524413980667603649783483184533471777",
  "embedded_ipv4": "192.0.2.33",
  "embedding": "nat64",
  "ranges": [
    {
      "cidr": "64:ff9b::/96",
      "name": "IPv4-IPv6 Translation",
      "rfc": "RFC 6052",
      "registry": "ipv6-special-purpose",
      "source": true,
      "destination": true,
      "forwardable": true,
      "globally_reachable": true,
      "reserved_by_protocol": false,
      "via": "address"
    },
    {
      "cidr": "192.0.2.0/24",
      "name": "Documentation (TEST-NET-1)",
      "rfc": "RFC 5737",
      "registry": "ipv4-special-purpose",
      "source": false,
      "destination": false,
      "forwardable": false,
      "globally_reachable": false,
      "reserved_by_protocol": false,
      "via": "embedded_ipv4"
    }
  ],
  "globally_reachable": false,
  "network": {
    "cidr": "64:ff9b::/96",
    "prefix": 96,
    "first": "64:ff9b::",
    "last": "64:ff9b::ffff:ffff",
    "size": "4294967296",
    "netmask": null
  },
  "cidr_matches": [],
  "notes": [
    "Host bits are set: the network is 64:ff9b::/96."
  ]
}
Same call as an MCP tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ip_inspect",
    "arguments": {
      "address": "64:ff9b::c000:221/96"
    }
  }
}

Teredo address

curl 'https://util.caruana.me/api/ip/inspect?address=2001%3A0%3A4136%3Ae378%3A8000%3A63bf%3A3fff%3Afdd2'

Response 200

{
  "version": 6,
  "input": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
  "canonical": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
  "expanded": "2001:0000:4136:e378:8000:63bf:3fff:fdd2",
  "zone": null,
  "integer": "42540488182158724593221357832373272018",
  "embedded_ipv4": "192.0.2.45",
  "embedding": "teredo",
  "ranges": [
    {
      "cidr": "2001::/23",
      "name": "IETF Protocol Assignments",
      "rfc": "RFC 2928",
      "registry": "ipv6-special-purpose",
      "source": false,
      "destination": false,
      "forwardable": false,
      "globally_reachable": false,
      "reserved_by_protocol": false,
      "via": "address"
    },
    {
      "cidr": "2001::/32",
      "name": "TEREDO",
      "rfc": "RFC 4380, RFC 8190",
      "registry": "ipv6-special-purpose",
      "source": true,
      "destination": true,
      "forwardable": true,
      "globally_reachable": null,
      "reserved_by_protocol": false,
      "via": "address"
    },
    {
      "cidr": "192.0.2.0/24",
      "name": "Documentation (TEST-NET-1)",
      "rfc": "RFC 5737",
      "registry": "ipv4-special-purpose",
      "source": false,
      "destination": false,
      "forwardable": false,
      "globally_reachable": false,
      "reserved_by_protocol": false,
      "via": "embedded_ipv4"
    }
  ],
  "globally_reachable": false,
  "network": null,
  "cidr_matches": [],
  "notes": [
    "Teredo (RFC 4380): server 65.54.227.120, client port 40000; the client's IPv4 address is stored inverted in the last 32 bits."
  ]
}
Same call as an MCP tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ip_inspect",
    "arguments": {
      "address": "2001:0:4136:e378:8000:63bf:3fff:fdd2"
    }
  }
}