Full geolocation and network lookup for an IPv4 address, IPv6 address, or resolvable hostname. Returns country, continent, ASN, organisation name, and — as of v0.1 — the most-specific announced BGP prefix covering the IP. Cached for 7 days.
| Field | Type | Description |
|---|---|---|
| ip | string | Resolved IP address. May differ from input when a hostname is provided. |
| country_code | string | ISO 3166-1 alpha-2 code, e.g. "AU". |
| country | string | Full country name, e.g. "Australia". |
| country_flag | string | Unicode flag emoji, e.g. "🇦🇺". |
| continent | string | Full continent name, e.g. "Oceania". |
| as_number | number | ASN as an integer, e.g. 13335. |
| as_description | string | Organisation name from the routing registry, e.g. "CLOUDFLARENET". |
| cidrnew | string|null | Most-specific announced BGP prefix containing this IP, e.g. "1.1.1.0/24". null when the ASN has no prefix entries in the database. |
| error | null|string | Null on success. Error message on failure. |
Returns all CIDR prefixes announced by an ASN, annotated with country and continent data.
Now also includes pre-computed announcement size stats so consumers don't need
to iterate the full prefix list. :as_number accepts a bare integer or an
AS-prefixed string (e.g. 13335 or AS13335).
Cached for 24 hours.
| Field | Type | Description |
|---|---|---|
| as_number | number | The ASN as an integer. |
| as_description | string | Organisation name from the registry. |
| ipv4_countnew | number | Total IPv4 host addresses across all announced prefixes (sum of 2^(32−prefixLen)). |
| ipv6_prefix_countnew | number | Number of IPv6 prefix entries. IPv6 address space is too large to represent as a single sum. |
| cidrs | object[] | Array of prefix objects. |
| cidrs[].cidr | string | CIDR notation, e.g. "1.1.1.0/24". |
| cidrs[].country_code | string | ISO 3166-1 alpha-2 code for this prefix's allocation. |
| cidrs[].country | string | Full country name for this prefix. |
| cidrs[].continent | string | Full continent name for this prefix. |
| error | null|string | Null on success. |
Search ASNs by multiple input types — automatically detected from the query string.
Returns up to 25 matching { as_number, as_description } results.
| Input | Strategy |
|---|---|
| CIDR prefixnew | e.g. 1.1.1.0/24 — exact match against the prefix table. Returns the owning ASN. |
| IP address | e.g. 1.1.1.1 — resolves to the owning ASN via the IP range table. |
| AS number / "AS1234" | e.g. 13335 or AS13335 — direct lookup by number, single result. |
| Org name | e.g. cloudflare — case-insensitive partial match against organisation names, up to 25 results. |
Traceroute hop annotation — returns the reverse-DNS record, the ASN details, the internet exchange the address sits on if any, and a best-effort "PoP" (point of presence) match. An address inside a peering LAN is at that exchange by definition, so it places the hop outright; otherwise the PoP is derived from parsing the PTR against known carrier naming conventions (Hurricane Electric, Cogent, GTT, Zayo, Lumen/Level3, NTT). When no carrier pattern fits, a tier-2 "scatter" pass looks for 3-letter IATA hub codes and known city names anywhere in the hostname. Supports IPv4 and IPv6. Auto-generated IPv6 PTRs (e.g. residential Comcast nibble-hex labels) are detected and stripped before matching. Cached for 24 hours; rate-limited to 300 requests/minute per client IP.
| Field | Type | Description |
|---|---|---|
| ip | string | The IP as supplied in the URL. |
| ip_version | 4 | 6 | null | Address family. null only on 400 errors. |
| ptr | string|null | Reverse-DNS hostname. null when no PTR is published or lookup timed out (2s). |
| asn | object|null | ASN metadata (same shape as /api/v2/ip). null when the IP is not in the routing table. |
| asn.number | number | AS number as integer. |
| asn.name | string | Organisation name from the registry. |
| asn.country_code | string | ISO 3166-1 alpha-2 country code. |
| ix | object|null | The internet exchange whose peering LAN contains this address, or null — which is the answer for almost every address. The full record, including every LAN and member, is at /api/v2/ix/ip/:ip. |
| ix.name / ix.city / ix.country | string|null | Exchange name and location. country is PCH's country name ("Germany"), not a code — unlike every other country field here. |
| ix.prefix | string | The peering LAN that matched. |
| ix.member | object|null | The network whose port holds this exact address, when PCH has it on file. null means not recorded, never "probably". |
| ix.source / ix.license | string|null | Attribution for the exchange data (Packet Clearing House, CC BY-NC-SA 3.0). Render these wherever you render ix. |
| pop | object|null | Matched PoP annotation, or null when nothing matched. |
| pop.iata | string | Canonical 3-letter IATA code for the PoP city. null on an exchange match when the exchange has no IATA code. |
| pop.city | string | City name. |
| pop.country | string | ISO alpha-2 country code. |
| pop.lat / pop.lon | number | Airport coordinates (proxy for PoP location). |
| pop.matched | string | Origin of the match: ix:<id>, carrier:<suffix> or scatter:<token>. |
| pop.confidence | "high"|"medium"|"low" | high = peering-LAN match or carrier pattern; medium = scatter hit whose country agrees with the ASN country; low = scatter hit only. |
| ptr_style | "normal"|"auto"|"auto-prefix"|null | auto = PTR was auto-generated (no hint); auto-prefix = we stripped the auto label and still matched the suffix. |
| error | null|string | Null on success. Error message on 400 (invalid IP) or 429 (rate-limited). |
Provenance for the topology dataset this instance is serving. Every other routing response embeds the same block, so a caller can always state what it is showing and when it was observed. Fetch this once to decide whether the routing endpoints are worth calling at all: 404 means no topology is loaded here, which is a normal state — a database image built before the routing tables existed, or a web image newer than its database image mid-rollout — and not an error. Cached for 1 hour.
| Field | Type | Description |
|---|---|---|
| rib_ts | string | ISO 8601 timestamp of the RIB dump the data was parsed from — when the internet looked like this, not when it was loaded. |
| collectors | string | Comma-separated collectors that contributed, e.g. "route-views2,rrc00". |
| peer_count | number | Distinct collector peers whose AS_PATHs went into the snapshot. This is the denominator for every observations and peers_seen figure elsewhere. |
| route_entries | number | Route entries parsed across all collectors. |
Observed BGP topology for an autonomous system: the networks that carry
its traffic, the networks it carries traffic for, and every AS seen
adjacent to it in a routing path. Derived from bulk MRT routing tables
(RouteViews route-views2 and RIPE RIS rrc00), which is the only way to
answer "who provides transit to this network". Related networks
come back named, joined in-database, so rendering a
peering table costs one request rather than one lookup per row.
Accepts 15169 or AS15169. Cached for 1 hour.
Everything here is an observation. These are AS_PATHs
seen by a specific set of collector peers at a specific time, so every
response embeds a snapshot block and callers are expected to
show it. Two claims the data does not support:
adjacency is not peering (two ASes next to each other in
a path may be in a transit, settlement-free peering or customer
relationship, and routing data cannot tell them apart, which is why the
field is neighbours), and upstreams are
inferred from the AS immediately preceding the origin, so for a
tier-1 that buys transit from nobody it surfaces that network's peers
instead. The response carries inferred: true so this cannot
be missed.
| Parameter | Default | Description |
|---|---|---|
| limit | 100 | Caps each of upstreams, downstreams and neighbours independently. Clamped to 500. The *_count fields are unaffected, so a truncated list is always detectable. |
| Field | Type | Description |
|---|---|---|
| as_number | number | The AS as supplied in the URL, normalised to an integer. |
| name | string|null | Operator name. null when the AS is observed in paths but absent from the name dataset. |
| prefixes_v4 / prefixes_v6 | number | Distinct prefixes observed originating from this AS, per address family. |
| addresses_v4 | number | Addresses covered by those v4 prefixes. Summed from the observed prefix list, not from the registry or this service's own per-ASN size fields, which disagree with observed BGP in both directions. There is deliberately no addresses_v6: the figure exceeds any integer type worth carrying and nobody reasons about it, so IPv6 is counted in prefixes. |
| degree_v4 / degree_v6 | number | Distinct adjacent ASes per address family. |
| upstream_count | number | Total upstreams, before limit is applied. |
| downstream_count | number | Total downstreams, before limit is applied. |
| upstreams | array | Networks seen immediately before this AS where it is the origin, most-observed first. Inferred — see above. |
| downstreams | array | The inverse: networks for which this AS appears as the upstream. |
| neighbours | array | Every adjacent AS in either direction, most-observed first. |
| upstreams[].as_number | number | The related AS. |
| upstreams[].name | string|null | Operator name for the related AS, already resolved. |
| upstreams[].af | 4 | 6 | Address family the adjacency was observed in. An AS pair adjacent over both appears twice. |
| upstreams[].observations | number | How many collector peers saw this adjacency. Weight it against snapshot.peer_count; a 1-of-74 adjacency is not the same claim as 68-of-74. |
| inferred | true | Always present and always true. Do not render these relationships as fact. |
| snapshot | object | Provenance block, same shape as /api/v2/routing/snapshot. |
How the internet actually reaches one address: every announcement
covering it, most specific first, each with the AS originating it and how
many collector peers saw that origin. This is strict BGP origin, which is
a different and stricter question than "which ASN is this IP
registered to" that /api/v2/ip/:ip answers. IPv4 and
IPv6. Cached for 1 hour.
routed: false is a real answer, not a 404 — the address is
allocated but not reachable, or announced only where our collectors
cannot see. moas: true means the most specific
prefix is announced by more than one AS: legitimate multi-homing or
anycast, or a hijack. It is reported, never adjudicated. Note that two
different prefixes covering one address is ordinary
deaggregation and does not set moas.
A leaked default route (0.0.0.0/0, ::/0) covers
every address and is never listed.
| Field | Type | Description |
|---|---|---|
| ip | string | The address as supplied in the URL. |
| routed | boolean | false when no observed prefix covers the address. |
| covering | array | Covering announcements, longest prefix first, then most-observed. Capped at 8. |
| covering[].prefix | string | The announced CIDR block. |
| covering[].origin_asn | number | AS at the end of the AS_PATH for that prefix. |
| covering[].name | string|null | Operator name for the origin, already resolved. |
| covering[].peers_seen | number | Collector peers that saw this prefix from this origin. Weigh against snapshot.peer_count. |
| covering[].rpki_state | string|null | Precomputed RPKI state of this announcement: valid | invalid | not-found, as on /api/v2/rpki/validate. null when this instance has no RPKI data. |
| covering[].rpki_reason | string|null | as | length when invalid; null otherwise. |
| covering[].irr_state | string|null | Precomputed IRR state: registered | covered | mismatch | missing, as on /api/v2/irr/snapshot. null when this instance has no IRR data. |
| moas | boolean | More than one origin on the most specific covering prefix. |
| origin_count | number | Distinct origins on that most specific prefix. 0 when unrouted. |
| snapshot | object | Provenance block, same shape as /api/v2/routing/snapshot. |
Everything observed at, above and below one prefix: who originates it,
which shorter announcements cover it, and what is announced inside it.
IPv4 and IPv6; the slash can be sent literally or as %2F.
Host bits are zeroed before lookup and the canonical form is echoed
back, so 8.8.8.8/24 answers as 8.8.8.0/24
rather than as a miss. Cached for 1 hour.
routed: false is a real answer, not a 404 — nothing was seen
announcing that exact prefix, though covering or more-specific routes may
still be listed. More than one entry in origins is the same
MOAS signal as on /api/v2/routing/ip/:ip:
multi-homing, anycast or a hijack, reported, never
adjudicated. A leaked default route covers everything and says
nothing, so 0.0.0.0/0 and ::/0 are never listed
as less-specifics.
Every row in origins, less_specifics and
more_specifics.rows also carries its precomputed
rpki_state, rpki_reason and irr_state,
exactly as on /api/v2/routing/ip/:ip, so a
prefix page needs no per-row RPKI or IRR lookups. A null state
means that dataset is not loaded on this instance, never "bad".
| Field | Type | Description |
|---|---|---|
| prefix | string | The canonical prefix that was looked up. |
| routed | boolean | false when no collector peer saw this exact prefix announced. |
| origins | array | Origin ASes of the exact prefix, most-observed first. Each has origin_asn, name, peers_seen, rpki_state, rpki_reason and irr_state; the prefix itself is not repeated. |
| less_specifics | array | Strictly covering announcements, most specific first, each with prefix, origin_asn, name and peers_seen. Capped at 20, which is the whole covering chain in practice. |
| more_specifics.count | number | Every announcement strictly inside the prefix, uncapped. |
| more_specifics.rows | array | The first 200 of those in address order, same shape as less_specifics. Compare against count to detect truncation. |
| snapshot | object | Provenance block, same shape as /api/v2/routing/snapshot. |
The largest networks by one measure, from the same per-AS figures /api/v2/routing/asn/:as returns. Rows come back named, so a leaderboard is one request. Cached for 1 hour.
Every figure is what the collectors observed, not what a registry
allocated: addresses counts IPv4 space seen announced, and
upstreams / downstreams rank by the same
inferred relationships as the per-AS endpoint, so a
tier-1's upstream count is really its peers.
| Parameter | Default | Description |
|---|---|---|
| by | addresses | One of addresses (IPv4 addresses, ties broken by prefix count), prefixes (v4 + v6), upstreams, downstreams or degree (adjacent ASes, v4 + v6). Anything else is a 400 naming the options. |
| limit | 100 | Rows returned, clamped to 1–500. There is no offset. |
| Field | Type | Description |
|---|---|---|
| by | string | The measure applied. |
| rows | array | Largest first, AS number as the final tie-break so the order is stable. |
| rows[].as_number / name | number / string|null | The AS and its operator name. |
| rows[].prefixes_v4 / prefixes_v6 / addresses_v4 | number | Observed origination, as on /api/v2/routing/asn/:as. |
| rows[].degree_v4 / degree_v6 | number | Distinct adjacent ASes per address family. |
| rows[].upstream_count / downstream_count | number | Inferred relationship counts. |
| snapshot | object | Provenance block, same shape as /api/v2/routing/snapshot. |
Registration and routing totals for every country that has at least one delegated AS number, largest IPv4 footprint first. Cached for 1 hour.
Country here is where the AS number is registered, not where
the addresses are used. It comes from the RIRs' delegated
statistics (the same data as the RDAP
endpoints), and every prefix an AS originates is counted under that
AS's registration country — a US-registered global CDN counts once,
for the US, wherever its space is actually announced or used. Label it
"registered in", never "located in". Registry
pseudo-codes such as EU appear with name: null,
because the registries really do file AS numbers under them.
Needs both the routing and the registry dataset: a 404 carries
"no routing snapshot loaded" or "no registry dataset
loaded" to say which is missing.
| Field | Type | Description |
|---|---|---|
| countries | array | One row per registration country, addresses_v4 descending. |
| countries[].cc | string | Registry country code, upper-case. |
| countries[].name | string|null | Country name; null for registry pseudo-codes. |
| countries[].asns_registered | number | AS numbers delegated to the country — every number in every delegated range, routed or not. |
| countries[].asns_routed | number | Of those, how many were seen originating at least one prefix. |
| countries[].prefixes_v4 / prefixes_v6 / addresses_v4 | number | Observed origination of those routed ASes, summed. |
| snapshot | object | Routing provenance block, same shape as /api/v2/routing/snapshot. |
The routed networks registered in one country, largest IPv4 footprint
first, with that country's totals row. :cc is a two-letter
code, case-insensitive. The same registration-country
caveat as /api/v2/routing/country
applies: this lists networks whose AS number was delegated in the
country, not networks that operate there. Cached for 1 hour.
A real country with nothing registered is a 200 with zeros, not a 404 —
that is an answer. 404 "unknown country" means the code
names no country at all: not two letters, or neither an ISO code nor
present in any registry's statistics.
| Parameter | Default | Description |
|---|---|---|
| limit | 100 | Rows returned, clamped to 1–500. |
| offset | 0 | Rows to skip, clamped to 0–1,000,000. Page until offset reaches total. |
| Field | Type | Description |
|---|---|---|
| cc | string | The code, upper-cased. |
| name | string|null | Country name; null for registry pseudo-codes. |
| totals | object | asns_registered, asns_routed, prefixes_v4, prefixes_v6, addresses_v4 — the country's row from /api/v2/routing/country. |
| total | number | The true length of the list rows pages through (equal to totals.asns_routed). |
| rows | array | Routed ASes, each with as_number, name, prefixes_v4, prefixes_v6, addresses_v4, upstream_count and downstream_count. |
| snapshot | object | Routing provenance block, same shape as /api/v2/routing/snapshot. |
FBI IC3 malicious-IP reputation. Answers "is this IP listed in an FBI IC3
Cybersecurity Advisory (a 'flash')?" from the rolling last year of advisories at
ic3.gov/CSA, alongside the geo/ASN summary — one call for where/whose an IP is and
whether the FBI has named it. A clean IP returns 200 with
ic3.listed = false (not 404). This is provenance, not a verdict:
advisory IPs age and get reassigned, and advisories occasionally list victim/sinkhole
IPs — weigh it as one signal, never a standalone block. Cached 24h.
| Field | Type | Description |
|---|---|---|
| ip | string | The IP as supplied. |
| country / country_code / country_flag / continent | string|null | Geo summary (same source as /api/v2/ip); null when the IP isn't in the DB. |
| as_number / as_description | number|string|null | Owning ASN. |
| ic3.listed | boolean | True if the IP matches one or more advisories. |
| ic3.count | number | Number of matching advisory rows. |
| ic3.advisories[] | array | Each: advisory_id, title, pub_date, source_url (the advisory PDF), cidr (the listed entry). |
| error | null|string | Null on success; message on 400 (invalid IP). |
| Route | Returns |
|---|---|
| /api/v2/threat/list | Plain text — every listed IP, one per line (hosts bare, ranges as CIDR). Firewall URL-table / external-connector feed. |
| /api/v2/threat/asn/:as | JSON { as_number, ic3_count, iocs[] } — listed IOCs attributed to an ASN, each ioc carrying the advisory that named it (advisory_id, title, pub_date, source_url). |
A curated, plain-language "what is this network" TLDR for well-known ASNs —
what it's used for, its location, and notable / interesting facts. Accepts
13335 or AS13335. AI-generated, best-effort context
(see the disclaimer field): not authoritative and carries no guarantee of
accuracy. body_markdown is a small markdown subset meant for client-side
rendering. Only a curated set of ASNs has an entry — any other returns 404
(a normal answer, not an error). The source files are public and editable via
source_url (the co-op repo). Cached 24h.
| Field | Type | Description |
|---|---|---|
| as_number | number | The ASN, as an integer. |
| name | string|null | Operator name. |
| location | string|null | Primary geography, or Global. |
| tags[] | array | Short lowercase labels (e.g. cdn, transit). |
| generated | string | Provenance of the text — currently always ai. |
| body_markdown | string | The description body, a small markdown subset (headings, lists, bold/italic, links). |
| disclaimer | string | Fixed AI-generated / no-accuracy-guarantee notice. |
| source_url | string | Link to the source markdown in the public co-op repo. |
| error | null|string | Null on success; message on 400 (invalid AS) / 404 (no entry). |
Provenance and licence for the internet-exchange dataset this instance is
serving. Every other /api/v2/ix/* response embeds the same
block. Fetch this once to decide whether the exchange endpoints are worth
calling at all: 404 means no exchange data is loaded here,
which is a normal state on a database image built before these tables
existed, and not an error. Cached for 1 hour.
Attribution is required, not optional. The data is
Packet Clearing House's, under
CC BY-NC-SA
3.0: free to redistribute non-commercially, with attribution, under the
same terms. That is why source and license are
fields in the response rather than a footnote here — if you render this
data, render those too.
| Field | Type | Description |
|---|---|---|
| collected_at | string | ISO 8601 timestamp of the collection run, not of the image build. |
| source | string | Upstream dataset. Display it. |
| license | string | Licence the data is redistributed under. Display it. |
| exchanges | number | Exchanges in the directory, including planned, deprecated and defunct ones. |
| prefixes | number | Peering LANs across all exchanges, both address families. |
| members | number | Individual member addresses recorded on those LANs. |
The exchange directory, biggest first, optionally narrowed to a region
and/or a country, with a region facet for building a picker. Every
directory entry is included whatever its status —
planned, deprecated and defunct exchanges too — so filter on that field
if you only want live ones. Cached for 1 hour.
Attribution travels in snapshot. This is
Packet Clearing House data under CC BY-NC-SA 3.0, exactly as described on
/api/v2/ix/snapshot; render
snapshot.source and snapshot.license wherever
you render the list. members is what PCH has on file, not
what is live, so a zero is not evidence of an empty exchange.
| Parameter | Default | Description |
|---|---|---|
| region | — | Exact region name, case-insensitive, e.g. Europe. Take the values from regions. |
| country | — | Exact country name, case-insensitive, e.g. Germany — the upstream publishes no codes. Either filter over 64 characters is a 400. |
| limit | 100 | Rows returned, clamped to 1–500. |
| offset | 0 | Rows to skip, clamped to 0–100,000. |
| Field | Type | Description |
|---|---|---|
| total | number | Exchanges matching the filters, before paging. |
| regions | array | { region, count } per region, under the country filter but not the region filter, so a picker does not collapse to the region already chosen. |
| rows | array | Exchanges, most members first, then by name and id so paging never repeats or skips a row. |
| rows[].id | number | Packet Clearing House exchange id — the :id for /api/v2/ix/:id. |
| rows[].name / city / country / region / iata | string|null | Directory entry. country is a name, not a code. |
| rows[].status | string | Exchange status, same values as /api/v2/ix/:id. |
| rows[].members | number | Distinct networks on file. Not the same figure as member_count on /api/v2/ix/:id, which counts member addresses (a dual-stack member is two). |
| rows[].ports | number | Connected ports as recorded upstream. |
| rows[].traffic | number | Reported peak traffic in bits per second (traffic_bps on /api/v2/ix/:id). 0 where unreported, which is common. |
| snapshot | object | Provenance and licence block, same shape as /api/v2/ix/snapshot. |
Find exchanges by name, city or country. Substring match across all three,
with exact and prefix matches ordered first and dead exchanges last, so
?q=amsterdam and ?q=AMS-IX both put the obvious
answer at the top. Returns the exchange summary only — call
/api/v2/ix/:id for LANs and members. Cached for 1 hour.
| Parameter | Default | Description |
|---|---|---|
| q | — | Required, at least 2 characters. Shorter terms 400 rather than returning a slice of the whole directory. |
| limit | 25 | Maximum results. Clamped to 100. |
| Field | Type | Description |
|---|---|---|
| query | string | The term as supplied. |
| count | number | Results returned, after limit. |
| results | array | Exchange summaries, same shape as the top level of /api/v2/ix/:id minus prefixes and members. |
| snapshot | object | Provenance block, same shape as /api/v2/ix/snapshot. |
Is this address sitting on a peering LAN, and whose port is it? This is the endpoint worth building on: a traceroute hop inside a peering LAN is at that exchange, which locates it far more reliably than an rDNS guess — the exchange's coordinates apply to the interface, not to the network that owns it. IPv4 and IPv6. Cached for 1 hour.
on_ix: false is the ordinary answer, not a 404 — most addresses
are not on an exchange. ix.member names the network holding the
port when Packet Clearing House has that exact address on file, and is
null otherwise; it is an exact-address match, so there is no
half-answer to misread. Deprecated LANs are matched deliberately — a hop on
a retired peering LAN still crossed that exchange — and
ix.prefix_status says so.
ix is singular, and sometimes that is one of two
true answers. Packet Clearing House records a handful of fabrics
under more than one exchange id — 206.72.210.0/23 is listed by
both 373 and 2450, which are the same Los Angeles
exchange — so also_recorded_as sits beside ix and
names every other exchange whose active LAN also covers the
address. It is [] for an unambiguous address, which is nearly
all of them. ix itself is unchanged; nothing that worked before
moves.
Anything covering the address counts here, not only an identical LAN: a
carve-out registered by a different exchange is a competing claim on where
the address lives, and that is precisely what the field exists to expose.
Compare related on /api/v2/ix/:id, which
asks the narrower question of whether two entries are the same fabric.
| Field | Type | Description |
|---|---|---|
| ip | string | The address as supplied in the URL. |
| on_ix | boolean | false when no peering LAN covers the address. |
| ix | object|null | The matched exchange, or null. Most specific LAN wins where blocks overlap. |
| ix.prefix | string | The peering LAN that matched. |
| ix.prefix_status | string | Active, Deprecated, Unknown or Defunct — the LAN's status, not the exchange's. |
| ix.participants | number | Ports on that LAN as recorded upstream. |
| ix.lat / ix.lon | number|null | Exchange coordinates. This is what makes the match useful for geolocating a hop. |
| ix.iata | string|null | Nearest airport code, for ~25% of exchanges. Joins onto the same PoP vocabulary /api/v2/hop/:ip uses. |
| ix.member | object|null | The network occupying the address, when recorded. |
| ix.member.as_number | number | AS holding the port. |
| ix.member.name | string|null | Operator name, resolved in-database from the routing dataset, falling back to the upstream string. |
| ix.member.rdns | string|null | PTR recorded upstream. Compare against the live PTR from /api/v2/hop/:ip. |
| ix.member.peering_policy | string|null | Open, Selective, Restrictive — as declared by the member. |
| also_recorded_as | array | Other exchanges whose active LAN also covers this address. [] when the address is unambiguous. Always present. |
| also_recorded_as[].pch_id | number | The other exchange's id. Named pch_id, not id, because it identifies a different record from ix. |
| also_recorded_as[].name / city / country / status / ports | — | The other exchange's own directory entry. |
| also_recorded_as[].member_count | number | Member addresses on that record. The size gap is usually how you tell the fuller entry from the thinner one. |
| also_recorded_as[].prefix / prefix_status / participants | — | The covering LAN that made it a match, as recorded against that exchange. |
| also_recorded_as[].pch_url | string | Deep link to the other exchange upstream. |
| snapshot | object | Provenance block, same shape as /api/v2/ix/snapshot. |
Every internet exchange a network is present on, with the address it holds
there. One entry per exchange even for a dual-stack member on several
ports. Pairs naturally with /api/v2/routing/asn/:as: that says
who a network exchanges traffic with, this says where it
does so. Accepts 15169 or AS15169. Cached for 24
hours.
An empty list is a real answer. Membership here is what Packet Clearing House has recorded, not what is live: roughly half the exchanges in the directory have no membership on file at all, and a network may also peer entirely privately. Absence is not evidence of absence.
| Parameter | Default | Description |
|---|---|---|
| limit | 200 | Maximum exchanges returned. Clamped to 500. |
| Field | Type | Description |
|---|---|---|
| as_number | number | The AS as supplied in the URL, normalised to an integer. |
| count | number | Exchanges returned, after limit. |
| exchanges | array | Exchange summaries, each with the member's own ip, rdns and peering_policy at that exchange. |
| snapshot | object | Provenance block, same shape as /api/v2/ix/snapshot. |
One exchange in full: where it is, its peering LANs across both address
families, and the networks on them. Members come back named
and ordered by their own connectivity, joined in-database against the
routing dataset — so rendering a members table costs one request rather
than one lookup per row, and the default page is the networks worth naming.
The :id is Packet Clearing House's own exchange id, which
pch_url links back to. Cached for 1 hour.
Deprecated and defunct LANs are included with their own
status, because a hop on a retired peering LAN still
identifies the exchange it crossed. Filter on that field if you only want
live ones.
One fabric is sometimes two directory entries. Packet
Clearing House occasionally carries the same physical exchange under two
ids, with nothing upstream linking them: 373 “Any2
California” and 2450 “Coresite - Any2 West”
are both in Los Angeles, both advertise the identical active LANs
206.72.210.0/23 and 2001:504:13::/64, and 2450's
586 member addresses are a strict subset of 373's 718. related
names the other entries. It is [] for 1,296 of the 1,327
exchanges in the directory, so treat a non-empty one as a signal, not noise:
counting both ids as separate exchanges inflates any total you derive.
Matched on the peering LAN, never on the name. A peering LAN is one L2 broadcast domain, so two entries advertising the same active prefix are the same fabric — a fact about the network, not a guess. Names are the opposite of a signal here: “Any2 California” and “Coresite - Any2 West” share no words, while the genuinely separate Any2 metros (Denver, Chicago, New York, each on its own LAN) share plenty. Deprecated prefixes are excluded because a retired block can be reassigned, and the prefixes must be identical rather than overlapping, because a carve-out of a larger block is a different claim.
We cross-link, we do not merge. Merging would mean electing
an authoritative record, which throws away the retired-LAN history only 373
carries, and every member port is recorded against a specific id, so
rewriting it would lose provenance. Both records stay exactly as published
and point at each other; deciding which one to show is yours. Relations are
direct neighbours, not transitive clusters — exchange 712 shares
an IPv4 LAN with 2402 and an IPv6 LAN with 2382,
so it lists both while 2382 lists only 712.
| Parameter | Default | Description |
|---|---|---|
| limit | 100 | Maximum member addresses. Clamped to 1000 — the largest exchange has over 6,000. member_count is unaffected, so truncation is always detectable. |
| members | — | Set to 0 to skip the member query and return the exchange and its LANs only. members comes back as [] rather than being dropped, so the response shape never changes. |
| q | — | Search the members, max 64 characters. An AS number (15169 or AS15169) matches that ASN exactly; anything else is a case-insensitive substring over network name, rDNS and address. limit still applies, to the matches. |
| Field | Type | Description |
|---|---|---|
| id | number | Packet Clearing House exchange id. |
| name | string | Exchange name, e.g. "AMS-IX Amsterdam". |
| city / country / region | string|null | Location. country is a name, not a code — the upstream publishes no code. |
| iata | string|null | Nearest airport code, present for ~25% of exchanges. |
| lat / lon | number|null | Exchange coordinates. |
| website | string|null | The exchange's own site. |
| status | string | Active, Planned, Unknown, Deprecated, Defunct or Not an exchange. Every directory entry is served so an id always resolves to something explicable. |
| ports | number | Connected ports as recorded upstream. |
| traffic_bps | number | Reported peak traffic in bits per second. 0 where unreported, which is common. |
| updated | string|null | When the upstream record was last touched, YYYY-MM-DD. |
| pch_url | string | Deep link to the upstream page for this exchange. |
| member_count | number | Total member addresses, before limit and q. |
| member_query | string|null | The member search applied, or null when members is unfiltered. |
| prefixes | array | Peering LANs, IPv4 first. Each has prefix, af (4 or 6), status and participants. |
| members | array | Networks on those LANs, most-connected first. Each has as_number, name, ip, rdns and peering_policy. |
| related | array | Other directory entries advertising an identical active LAN — the same fabric under another id. [] for all but 31 of the 1,327 exchanges. Always present, and unaffected by ?members=0. |
| related[].pch_id | number | The other exchange's id. Named pch_id, not id, because it identifies a different record from the one you asked for. |
| related[].name / city / country / status / ports | — | The other exchange's own directory entry, as published. |
| related[].member_count | number | Member addresses on that record. Uncapped, so the size gap against this exchange's member_count tells you which entry is the fuller one. |
| related[].shared_prefixes | array | The peering LANs both entries advertise as active. Sorted, so the array is stable between requests. |
| related[].pch_url | string | Deep link to the other exchange upstream. |
| snapshot | object | Provenance block, same shape as /api/v2/ix/snapshot. |
Provenance for the registry-allocation dataset this instance is serving.
Every other /api/v2/rdap/* response embeds the same block.
Fetch this once to decide whether the registry endpoints are worth calling
at all: 404 means no registry data is loaded here, which is
a normal state on a database image built before these tables existed, and
not an error. Cached for 1 hour.
Nothing here speaks RDAP. These endpoints answer the subset of questions an RDAP lookup is normally used for, out of a local table built from the five RIRs' daily delegated-extended statistics files. The point is that a consumer can stop making five third-party requests per page view.
| Field | Type | Description |
|---|---|---|
| collected_at | string | ISO 8601 timestamp of the collection run, not of the image build. |
| source | string | Upstream dataset description. |
| source_urls | object | The five files, keyed by registry. There is no single licence covering all of them, so the per-registry URL is the provenance — check each registry's own conditions of use before redistributing. |
| registries | object | Per-registry serial, generation date and row counts. This is how you tell a fresh answer from one built on a registry that quietly stopped republishing. |
| alloc_rows | number | Address allocations loaded, both families. |
| asn_rows | number | AS-number allocation ranges loaded. |
| whois | object|null | Provenance for the bulk-whois name dataset (RIPE NCC, APNIC, AFRINIC RPSL dumps): registries, per-dump dumps counts and Last-Modified, rows, and rows_gated (placeholder objects removed at build — see rdap/ip). null when this image has no name data. |
Which registry holds this address, in which country, since when, and under what status. IPv4 or IPv6. Cached for 1 hour.
Read the fields_absent array before rendering.
The delegated files carry no network name, organisation name or abuse
contact, so those fields are not merely null here — they are not in the
dataset. Rendering their absence as a fact about the network ("this
network has no abuse contact") would be false. The array names them
explicitly on every response so there is no need to guess.
Names come from two sources, and the response says which.
whois is the registry object from the free bulk RPSL dumps of
RIPE NCC, APNIC and AFRINIC, baked into this instance and
always answered locally. ARIN and LACNIC publish no anonymous bulk dump, so
their space is named only by detail, the lazily-filled RDAP
cache (a cold address gets detail: null and a background fetch).
netname is the convenience pick — bulk record first, RDAP cache
second — with source naming which. fields_absent
narrows to whatever is actually present; the bulk dumps never carry an
abuse contact.
Two limits on the bulk record. It is the most specific object within
what is loaded: end-user assignments smaller than /24 (IPv4) or /48
(IPv6) — some 5.4 million objects, mostly /29s — are left out, so an
address inside one gets the covering LIR object instead. And placeholder
objects every dump carries for space the registry does not manage
(IANA-BLK over 0.0.0.0/0, APNIC's
RIPE-CIDR-BLOCK over 193/8, and so on) are removed at build
time by requiring both ends of an object to fall in one holder's
delegation at the same registry.
status: "available" or "reserved" is a
real answer, meaning the registries positively record that nobody
holds this space. That is different from found: false, which
means the address falls outside what the RIRs publish at all — IANA
special-purpose space, roughly 14% of IPv4 (multicast 224/4, reserved
240/4, 0/8, 127/8 and friends). Both are 200s; a 404 is reserved for
"no dataset loaded".
| Field | Type | Description |
|---|---|---|
| query | string | The address as parsed. |
| found | boolean | Whether any delegated-statistics record covers it. |
| allocation.prefix | string | The covering CIDR as the registry publishes it. |
| allocation.rir | string | arin | ripencc | apnic | lacnic | afrinic. |
| allocation.cc | string | ISO alpha-2, or null when not recorded. |
| allocation.status | string | allocated | assigned | available | reserved. |
| allocation.allocated | string | Delegation date (YYYY-MM-DD), or null. |
| allocation.opaque_id | string | Holder id. Unique within its own registry only — always pair it with rir. |
| allocation.delegated | boolean | True for allocated/assigned; false for space nobody holds. |
| netname | object|null | { value, source, start_address, end_address } — the network name, with source whois-bulk or rdap-cache and the range of the object it came from. null when neither source has one. |
| whois | object|null | Bulk RPSL record: found, covered (whether this address's registry publishes a dump), record (start_address, end_address, rir, netname, country, status, org_handle, organisation, last_changed), a note explaining any miss, and source. null when this image has no name data. |
| detail | object|null | RDAP-cache record (name, organisation, abuse contact), when one has been fetched. Unchanged meaning: always the RDAP cache, never the bulk record. |
| fields_absent | array | RDAP fields this response cannot supply. See above. |
| source | object | The snapshot block. |
The registry record covering an entire CIDR block. Same response shape as
/api/v2/rdap/ip/:ip, including netname and
whois — where the bulk record, too, must contain the whole
block. Cached for 1 hour.
This is not the same question as asking about the block's first
address, and the difference bites. A block can span several
allocations and be covered by none of them: 8.8.0.0/16 contains 12 separate
registry records, so looking up 8.8.0.0 answers 8.8.8.0/22 with
every appearance of confidence. This endpoint requires containment of the
whole block and returns found: false when no single record
covers it, which is the truthful answer.
Host bits are tolerated: 8.8.8.8/24 is read as the /24
containing that address.
The registry record covering an AS number. Accepts 15169 or
AS15169. Cached for 1 hour.
Allocations are stored as closed ranges, so the response carries
as_start and as_end rather than a single number —
registries hand out 32-bit AS numbers in blocks, and the range is the record
that actually exists. A single assignment simply has both ends equal.
Every other prefix and AS number the same holder has, taken from the
opaque_id on any allocation response. This is the one field the
delegated files give that RDAP cannot cheaply be asked for in bulk: it
groups a registrant's resources without a name ever being involved.
?limit= caps each list (default 100, max 1000); the counts stay
uncapped. Cached for 1 hour.
The registry is part of the key, not decoration. An opaque id is unique within one registry only — LACNIC publishes small integers, ARIN hex digests, RIPE UUIDs — and nothing coordinates them, so two registries can emit the same string for unrelated organisations. An endpoint keyed on the id alone would silently merge them, which is why this one will not accept it.
| Field | Type | Description |
|---|---|---|
| prefixes | array | Address allocations held, up to limit. |
| asns | array | AS-number ranges held, up to limit. |
| prefix_count | number | Total held, uncapped. |
| asn_count | number | Total held, uncapped. |
Provenance and global counts for the RPKI dataset this instance is
serving. Every other /api/v2/rpki/* response embeds the same
block. Fetch this once to decide whether the RPKI endpoints are worth
calling at all: 404 means no RPKI data is loaded here,
which is a normal state on a database image built without it, and not an
error. Cached for 1 hour.
Validity is a statement about one snapshot. The VRPs are
rpki-client's validated
output as of generated_at, and the route states are
RFC 6811 origin validation precomputed at build time
for every announcement in the loaded routing
snapshot — not re-evaluated per request. ROAs are issued and revoked
continuously, so show the date beside any badge you render.
not_found — no ROA covers the route — is the normal state for
a large share of the table (about a quarter of it at the time of writing)
and is not a fault.
| Field | Type | Description |
|---|---|---|
| generated_at | string | ISO 8601 time rpki-client built the VRP set — how fresh the validation is, not when it was downloaded. |
| source | string | The export the VRPs were read from. |
| vrps | number | Validated ROA payloads loaded, after de-duplication. |
| aspas | number | ASPA records loaded. Small by design — see /api/v2/rpki/asn/:as. |
| by_ta | object | VRPs per trust anchor: afrinic, apnic, arin, lacnic, ripencc. |
| routes | object|null | Observed announcements per state: valid, invalid, not_found. null — not zeros — when the build had no routing data to validate, so "not computed" never reads as "no invalid routes". |
RFC 6811 route-origin validation of any (prefix, origin) pair against the loaded VRP set — an announcement that exists or one you are only planning, which is what makes it useful for "would this be accepted?" before it is made. Evaluated live against the VRPs, unlike the precomputed states on the other RPKI endpoints. Cached for 1 hour.
valid: a covering VRP names this origin and allows this
length. invalid: covered, but not valid — reason
length when a VRP names the right origin but the route is more
specific than its max_length, otherwise as
(including routes covered only by an AS0 ROA, which authorises nobody).
not-found: no VRP covers the prefix at all; that is the
normal state for much of the table and not an error.
An invalid is a mismatch with what the address holder published, not
proof of a hijack — stale or overly tight ROAs are the usual cause.
| Parameter | Default | Description |
|---|---|---|
| prefix | — | Required. IPv4 or IPv6 CIDR; host bits are zeroed and the canonical form echoed back. A bare address is read as a host route (/32 or /128). |
| asn | — | Required. Origin to test, 13335 or AS13335. 0 is refused: AS0 is a ROA marker, never a real origin. |
| Field | Type | Description |
|---|---|---|
| prefix | string | The canonical prefix validated. |
| asn | number | The origin validated. |
| state | string | valid | invalid | not-found. |
| reason | string|null | length | as when invalid; null otherwise. |
| vrps | array | Covering VRPs, most specific first and this origin's first within a length, each { prefix, max_length, asn, ta }. Capped at 50; the verdict is computed over all of them, so the cap never changes state. |
| snapshot | object | Provenance block, same shape as /api/v2/rpki/snapshot. |
Every VRP covering a prefix, whatever AS it names — "which ROAs
govern this space, for whom, and how specific may they go", without
guessing an origin for /api/v2/rpki/validate
first. An empty list means no ROA covers the prefix, so any announcement
of it is not-found. Cached for 1 hour.
A VRP naming AS 0 is an AS0 ROA: the holder is saying nobody
may originate that space, so it invalidates any route it covers that no
other VRP authorises.
| Parameter | Default | Description |
|---|---|---|
| prefix | — | Required. IPv4 or IPv6 CIDR; host bits are zeroed and the canonical form echoed back. A bare address is read as a host route. |
| Field | Type | Description |
|---|---|---|
| prefix | string | The canonical prefix looked up. |
| vrps | array | Covering VRPs, most specific first, then by AS, each { prefix, max_length, asn, ta }. Capped at 200. |
| count | number | Every covering VRP, uncapped. Compare against the length of vrps to detect truncation. |
| snapshot | object | Provenance block, same shape as /api/v2/rpki/snapshot. |
Everything RPKI says about one AS: the precomputed state of each
announcement it originates, the ROAs that name it, and its ASPA record.
Accepts 13335 or AS13335. An AS that publishes
nothing is a 200 with zeros and empty lists — "this network publishes
no RPKI" is the answer, not a miss. Cached for 1 hour.
ASPA is new and rare — aspa: null means
nothing. Only a few thousand networks have published an
Autonomous System Provider Authorization at all, so its absence is not a
misconfiguration and must not be rendered as one. When present,
providers lists the upstreams the AS has authorised; a single
provider of 0 is the AS declaring that it has no providers.
prefixes and roas.rows are each capped at
limit (default and maximum 5,000); summary.total
and roas.count are the true counts beside them, so truncation
is always detectable. prefixes lists problems first —
invalid, then not-found, then valid —
so a cap never hides the routes that need attention. Note the spelling:
the per-route state is not-found while the
summary key is not_found.
| Parameter | Default | Description |
|---|---|---|
| limit | 5000 | Cap on prefixes and roas.rows, 0-50000; above 50000 is clamped. Ask for more than the default when building a router filter: 16 networks have more than 5,000 ROAs. 0 skips both lists and returns only summary, roas.count and aspa — the cheap form for a badge or a count. Non-numeric is a 400. |
| Field | Type | Description |
|---|---|---|
| as_number | number | The AS as supplied, normalised to an integer. |
| summary | object | valid, invalid, not_found and total across every announcement this AS originates. Uncapped. |
| prefixes | array | Announcements, invalid first, then not-found, then valid, each group by prefix. Each { prefix, state, reason, peers_seen }; state and reason as on /api/v2/rpki/validate. |
| roas.count | number | VRPs naming this AS, uncapped. |
| roas.rows | array | Those VRPs by prefix, each { prefix, max_length, ta }. |
| aspa | object|null | { providers: [{ asn, name }] }, or null when the AS has no ASPA record — the common case. |
| snapshot | object | Provenance block, same shape as /api/v2/rpki/snapshot. |
Every RPKI-invalid announcement in the loaded routing snapshot, most widely seen first — the routes actually propagating despite failing validation rank highest, and the ones most networks already filter sink to the bottom. States are the build-time precompute described on /api/v2/rpki/snapshot. Cached for 1 hour.
An entry here is a mismatch, not an accusation. It means
the announcement disagrees with the ROAs its address holder published
at snapshot.generated_at; stale ROAs and traffic-engineering
more-specifics beyond max_length are far more common causes
than hijacks. That is why the list carries its snapshot.
| Parameter | Default | Description |
|---|---|---|
| limit | 100 | Rows returned. Above 500 is clamped to 500; 0 or anything non-numeric is a 400. |
| offset | 0 | Rows to skip. Non-numeric is a 400. |
| Field | Type | Description |
|---|---|---|
| total | number | Invalid announcements in the whole table, before paging. |
| rows | array | Ordered by peers_seen descending, then prefix and origin, so paging is stable. |
| rows[].prefix / origin_asn | string / number | The announcement. |
| rows[].name | string|null | Operator name for the origin, already resolved. |
| rows[].reason | string | as (origin not authorised) or length (authorised origin, too specific). |
| rows[].peers_seen | number | Collector peers that saw it. Weigh against the routing snapshot.peer_count. |
| snapshot | object | Provenance block, same shape as /api/v2/rpki/snapshot. |
Provenance and headline counts for the Internet Routing Registry dataset:
route objects and as-sets from eight registries — RADB, RIPE, ARIN,
APNIC, LACNIC, AFRINIC, ALTDB and NTTCOM. Every other
/api/v2/irr/* response embeds the same block.
404 means no IRR data is loaded here, a normal state and
not an error. Cached for 1 hour.
A route object is a claim, not an authorisation. IRR
data is self-asserted: anyone with an account on a registry like RADB
can register an object for any prefix. registered means an
object exists — the thing IRR-based prefix filters are built from — not
that the announcement is legitimate. RPKI
is the dataset for that question.
Each observed announcement gets one precomputed state, first match wins:
registered (an object with the same prefix and origin, in any
registry) > covered (a less-specific object with the same
origin) > mismatch (objects for the exact prefix, but only
with other origins) > missing (none of those).
| Field | Type | Description |
|---|---|---|
| generated_at | string | ISO 8601 time the collector assembled the dumps. |
| sources | object | Route objects (route + route6) per registry. |
| routes | number | Route objects loaded across all registries. |
| as_sets | number | as-set objects loaded. |
| route_states | object|null | Observed announcements per state (registered, covered, mismatch, missing). null when the build had no routing data to compare against. |
| registries | object | Per registry: dump serial (may be null) and last_modified. This is how you spot a registry that quietly stopped publishing. |
| failed | object | Optional registries that failed this build, keyed by name. {} when all loaded. |
Route objects registered for a prefix: every object for the exact prefix in any registry, the less-specific objects covering it, and how many more-specific objects sit inside it. The prefix length is required (a bare address is a 400); host bits are zeroed and the canonical prefix echoed back. Empty lists are a real answer, not a 404. Cached for 24 hours.
Two objects for one prefix and origin in different registries — or
objects for different origins — are normal: nothing reconciles the
registries, and stale objects are rarely cleaned up. Show
source, mnt_by and last_modified
so a reader can judge each claim.
| Field | Type | Description |
|---|---|---|
| prefix | string | The canonical prefix looked up. |
| exact | array | Every route object for exactly this prefix, by origin then registry. Uncapped. |
| covering | array | Less-specific route objects, most specific first. Capped at 50. |
| covering_count | number | Every less-specific route object, uncapped — compare against the length of covering to detect truncation. |
| more_specific_count | number | Route objects strictly inside the prefix. A count only; query a more-specific prefix to see them. |
| exact[] / covering[] | object | prefix, origin (number), source (registry), descr, mnt_by and last_modified (YYYY-MM-DD) — all as registered, any of the text fields may be null. |
| snapshot | object | Provenance block, same shape as /api/v2/irr/snapshot. |
The IRR view of one origin AS: the precomputed state of every
announcement it originates, every route object naming it as origin
(flagged by whether it is actually announced), and the as-sets that list
it directly. Accepts 13335 or AS13335. An AS with
nothing registered is a 200 with zeros. Cached for 1 hour.
prefixes and route_objects.rows are capped at
limit (default and maximum 5,000), as_sets at
5,000; summary.total, route_objects.count and
as_sets_count are the true counts beside them. Large networks
exceed these caps — AS13335 has over 56,000 route objects naming it — so
both lists put problems first: prefixes runs
mismatch, missing, covered,
registered, and route_objects.rows lists objects
that are not announced (often stale) before announced ones.
| Parameter | Default | Description |
|---|---|---|
| limit | 5000 | Cap on prefixes and route_objects.rows, 0-50000; above 50000 is clamped. 0 skips both lists and returns the summary, counts and as_sets. Non-numeric is a 400. |
| Field | Type | Description |
|---|---|---|
| as_number | number | The AS as supplied, normalised to an integer. |
| summary | object | registered, covered, mismatch, missing and total over every announcement this AS originates. Uncapped. |
| prefixes | array | Announcements, mismatch first, then missing, covered, registered, each group by prefix. Each { prefix, state }; states as defined on /api/v2/irr/snapshot. |
| route_objects.count | number | Route objects with this origin across all registries, uncapped. |
| route_objects.not_announced | number | How many of those this AS was not seen originating, uncapped. |
| route_objects.rows | array | Not-announced objects first, then by prefix. Each { prefix, source, descr, mnt_by, last_modified, announced }. announced: false is an object for a route this AS was not seen originating — often stale. |
| as_sets | array | { name, source } for every as-set listing this AS as a direct member, capped at 5,000. Not recursive: a set that includes it only through a nested set is not here. |
| as_sets_count | number | Sets listing this AS directly, uncapped. |
| snapshot | object | Provenance block, same shape as /api/v2/irr/snapshot. |
An as-set's objects in every registry that has one by that name, and
its recursive expansion to AS numbers — the list a bgpq4-style filter
would be built from. Names are case-insensitive and may be hierarchical
(AS8283:AS-COLOCLUE); at least one component must be an
AS- set name, so AS13335 or RS-FOO
is a 400. Cached for 1 hour.
The expansion is bounded and says so. Real as-sets
nest deeply and loop, so the walk stops at depth 6 below the root,
2,000 sets visited, or 50,000 ASNs, and sets truncated: true
whenever any bound cut it short — the big transit sets hit these. Never
present a truncated expansion as complete. Members are merged across
every registry holding a set of that name, which is what bgpq4 does
when pointed at all sources — but the same name in two registries can
belong to two different operators, so check objects when
that matters. Expansions are cached per server process, so repeat
requests for a big set are cheap.
| Parameter | Default | Description |
|---|---|---|
| asn_limit | 50000 | Cap on the inline expanded.asns list only, 0-50000; above is clamped. expanded.count and truncated still describe the whole expansion. Non-numeric is a 400. |
| Field | Type | Description |
|---|---|---|
| name | string | The set name, upper-cased. |
| found | boolean | true on a 200. |
| objects | array | One per registry holding the set, each { source, descr, members }. members is the raw list: AS numbers and nested set names. |
| expanded.asns | number[] | Every AS number reached, ascending, up to asn_limit. |
| expanded.count | number | AS numbers the expansion reached (within its bounds), whatever asn_limit trimmed from asns. |
| expanded.sets_visited | number | Sets looked up, including the root. |
| expanded.depth | number | Deepest nesting level reached below the root. |
| expanded.truncated | boolean | true when a depth, set or ASN bound stopped the walk. count is then a lower bound. |
| snapshot | object | Provenance block, same shape as /api/v2/irr/snapshot. |
The bgpq4-style prefix list for an as-set: expand it exactly as
/api/v2/irr/as-set/:name does (same bounds, same
cache), then every distinct route / route6
prefix whose origin is in the expansion, IPv4 first then IPv6, each in
address order. This is the list an IRR-based filter would accept for
the set — self-asserted claims, not a statement of legitimacy. Cached for
1 hour.
truncated: true means the filter is
incomplete — either the expansion hit a bound
(asns.truncated) or limit cut the list
(count is larger than the rows returned). Big transit sets
run to millions of prefixes: AS-HURRICANE expands to 25,657
ASNs and 1.8 million distinct prefixes.
| Parameter | Default | Description |
|---|---|---|
| af | all | 4, 6 or all. Anything else is a 400. |
| limit | 100000 | Prefixes returned, 0-200000; above is clamped. 0 returns only the counts. Non-numeric is a 400. |
| Field | Type | Description |
|---|---|---|
| name | string | The set name, upper-cased. |
| found | boolean | true on a 200. |
| asns.count | number | AS numbers in the expansion. |
| asns.truncated | boolean | A depth, set or ASN bound stopped the expansion. |
| prefixes | array | { prefix } per distinct prefix, IPv4 then IPv6, in address order, up to limit. |
| count | number | Distinct prefixes in total for this af, uncapped. |
| truncated | boolean | asns.truncated, or count exceeds the rows returned. |
| sources_used | string[] | Registries whose route objects contributed at least one prefix. |
| snapshot | object | Provenance block, same shape as /api/v2/irr/snapshot. |
Which baked datasets the database behind this instance actually has: for each dataset, whether every table it needs is present, with approximate row counts, plus when Postgres last started and the database size. The snapshot endpoints report provenance; this reports presence. A dataset endpoint answering 503 "tables missing" points here. Never cached.
| Field | Type | Description |
|---|---|---|
| database.started_at | string | When Postgres started. A time that keeps moving is a restart loop. |
| database.size_bytes | number | Size of the database. |
| datasets.<name>.complete | boolean | Every table the dataset needs exists. Names: geo, ic3, routing, registry, ix, rpki, irr. |
| datasets.<name>.tables | object | Per table: present and rows — a catalogue estimate, -1 if never analysed, null if absent. |
Returns the full country name as a plain text string. Ideal for shell pipelines. Accepts IPv4, IPv6, or any resolvable hostname. Cached for 7 days.
Returns the bare ASN number as plain text — no "AS" prefix.
Returns the full continent name as plain text.
Atlas is free and unmetered. If you're using it in something cool, consider supporting continued development.
♥ Donate