ipdex API

The open index of the IP world, as an API. Free tier: no API keys, no signup, CORS * — usable from a browser tab, a cron job, or a dotfile. Machine-readable spec: openapi.json · openapi.yaml.

Getting started

curl https://api.ipdex.io/v1/lookup/8.8.8.8

That's the whole onboarding. The Free tier is rate-limited to 60 requests/minute/IP, enforced at the edge; every response carries informational RateLimit-Limit / RateLimit-Policy headers. If you are hitting the limits with a real use case, we want to hear about it — open an issue on GitHub.

The shell shortcuts also exist on the site root: curl ipdex.io returns your bare IP; curl ipdex.io/json returns your compact connection snapshot. Neither is ever stored.

Data & versioning

Sources: IPinfo Lite, PeeringDB, the five RIRs' delegated statistics, and BGP tables — rebuilt and gate-validated nightly; a failed validation never publishes (the dataset is either yesterday's good build or today's good build, never a partial). Every response carries x-data-version, the content hash of the dataset that produced it; the changelog lists every published version. History tables (daily, monthly, allocation events) are append-only: rows are real observed snapshots, never interpolated, and missing periods are honestly absent rather than filled.

Endpoints

GET /v1/me

Full self-lookup from the edge (request.cf). Never stored.

200 Visitor snapshot + data version

request
curl https://api.ipdex.io/v1/me
200 · response
{
  "ip": "203.0.113.10",
  "ipVersion": 4,
  "asn": 13335,
  "asOrganization": "Example Networks",
  "country": "US",
  "city": "…",
  "region": "…",
  "timezone": "America/New_York",
  "colo": "EWR",
  "httpProtocol": "HTTP/3",
  "tlsVersion": "TLSv1.3",
  "clientTcpRtt": 12,
  "isTor": false,
  "dataVersion": "551c9b9a385b"
}

GET /v1/me/ip

Bare client IP as text/plain.

200 The IP address

request
curl https://api.ipdex.io/v1/me/ip
200 · response
203.0.113.10

GET /v1/lookup/{ip}

Resolve an IP to ASN, org and country from the index.

ParamInTypeNotes
ip* path string e.g. 8.8.8.8

200 Lookup result (asn/org/country null when unrouted/unknown) · 400 Invalid IP

request
curl https://api.ipdex.io/v1/lookup/8.8.8.8
200 · response
{
  "ip": "8.8.8.8",
  "version": 4,
  "asn": 15169,
  "asnType": "content",
  "org": "Google LLC",
  "orgSlug": "google-asia-pacific-pte-ltd",
  "country": "US",
  "source": "derived",
  "lastUpdated": "2026-06-12T19:43:43.885Z"
}

GET /v1/asn/{asn}

ASN summary.

ParamInTypeNotes
asn* path string e.g. AS15169

200 ASN record · 400 Invalid ASN · 404 Unknown ASN

request
curl https://api.ipdex.io/v1/asn/AS8452
200 · response
{
  "asn": 8452,
  "org": "TE-AS",
  "orgSlug": "eg-ix-route-servers",
  "country": "EG",
  "type": "isp",
  "domain": "te.eg",
  "allocatedDate": "1997-09-01",
  "prefixCountV4": 1703,
  "prefixCountV6": 9,
  "source": "derived",
  "lastUpdated": "2026-06-14T19:28:22.818Z",
  "rpki": { "valid": 1704, "invalid": 0, "total": 1719 }
}

GET /v1/prefix/{cidr}

A stored prefix's announcing origin(s) + RPKI status.

ParamInTypeNotes
cidr* path string CIDR; the slash is part of the path.

200 Prefix record · 400 Invalid CIDR · 404 Prefix not in our data

request
curl https://api.ipdex.io/v1/prefix/8.8.8.0/24
200 · response
{
  "prefix": "8.8.8.0/24",
  "version": 4,
  "origins": [
    {
      "asn": 15169,
      "org": "Google LLC",
      "rpki": "valid"
    }
  ],
  "source": "derived",
  "lastUpdated": "2026-06-16T00:00:00.000Z"
}

GET /v1/org/{slug}

An organization + a capped list of its ASNs.

ParamInTypeNotes
slug* path string e.g. google-llc

200 Org record · 400 Invalid slug · 404 Unknown org

request
curl https://api.ipdex.io/v1/org/cloudflare-sydney-llc
200 · response
{
  "slug": "cloudflare-sydney-llc",
  "name": "Cloudflare Sydney, LLC",
  "country": "US",
  "type": "unknown",
  "asnCount": 8,
  "asns": [
    {
      "asn": 14789,
      "type": "unknown",
      "country": "PK"
    },
    {
      "asn": 132892,
      "type": "unknown",
      "country": "US"
    }
  ],
  "source": "derived",
  "lastUpdated": "2026-06-12T19:43:43.885Z"
}

GET /v1/country/{cc}

Country overview (complements /v1/country/{cc}/history).

ParamInTypeNotes
cc* path string e.g. EG

200 Country record · 400 Invalid country code · 404 Unknown country

request
curl https://api.ipdex.io/v1/country/EG
200 · response
{
  "cc": "EG",
  "name": "Egypt",
  "rir": "afrinic",
  "totalV4": 24151552,
  "totalV6Prefixes": 21,
  "asnCount": 95,
  "source": "derived",
  "lastUpdated": "2026-06-12T19:43:43.885Z"
}

GET /v1/ix/{id}

An Internet Exchange (source: PeeringDB).

ParamInTypeNotes
id* path integer e.g. 31

200 IX record · 400 Invalid IX id · 404 Unknown IX

request
curl https://api.ipdex.io/v1/ix/1
200 · response
{
  "ixId": 1,
  "name": "Equinix Ashburn",
  "city": "Ashburn",
  "country": "US",
  "memberCount": 345,
  "source": "peeringdb",
  "lastUpdated": "2026-06-14T19:28:22.818Z"
}

GET /v1/facility/{id}

A colocation facility (source: PeeringDB).

ParamInTypeNotes
id* path integer e.g. 1

200 Facility record · 400 Invalid facility id · 404 Unknown facility

request
curl https://api.ipdex.io/v1/facility/1
200 · response
{
  "facId": 1,
  "name": "Equinix DC1-DC15,DC21-DC22 - Ashburn",
  "city": "Ashburn",
  "country": "US",
  "source": "peeringdb",
  "lastUpdated": "2026-06-14T19:28:22.818Z"
}

GET /v1/search

Grouped entity search: countries, networks (ASNs) and organizations.

Prefix matches rank above contains; an "AS" prefix on a numeric query is stripped (AS8452 ≡ 8452). Results are grouped with a per-group limit. Cached by the query string (never by the caller).

ParamInTypeNotes
q* query string e.g. vodafone
limit query integer Per-group result cap

200 Grouped results · 400 Empty or over-long q

request
curl 'https://api.ipdex.io/v1/search?q=vodafone'
200 · response
{
  "q": "vodafone",
  "dataVersion": "551c9b9a385b",
  "countries": [],
  "asns": [
    {
      "asn": 24835,
      "org": "Vodafone Data",
      "orgSlug": "vodafone-data",
      "cc": "EG"
    },
    {
      "asn": 38266,
      "org": "Vodafone Idea Ltd",
      "orgSlug": "vodafone-idea-ltd-3",
      "cc": "IN"
    },
    {
      "asn": 45271,
      "org": "Vodafone Idea Ltd",
      "orgSlug": "vodafone-idea-ltd",
      "cc": "IN"
    },
    {
      "asn": 55410,
      "org": "Vodafone Idea Ltd",
      "orgSlug": "vodafone-idea-ltd-2",
      "cc": "IN"
    },
    {
      "asn": 36935,
      "org": "Vodafone Data",
      "orgSlug": "vodafone-international-services-l-l-c",
      "cc": "EG"
    }
  ],
  "orgs": [
    {
      "slug": "vodafone-international-services-l-l-c",
      "name": "Vodafone International Services L.L.C",
      "cc": "EG",
      "type": "unknown"
  …

GET /v1/country/{cc}/history

Country history: monthly RIR allocation events + the daily stats series.

Both arrays ascending, numbers as numbers. `alloc` derives from the RIR delegated files’ per-record allocation dates (sparse — only months with events; sentinels bucket under XX). `daily` is our own gate-validated snapshot, accumulating since 2026-06. `monthly` is REGISTRY STATE per archived monthly snapshot, parsed from the RIRs’ historical delegated files (archives reach 2001–2005 depending on registry) — sparse: months whose snapshot is missing or failed its reconciliation gate simply do not exist (never interpolated). When the requested daily window exceeds 400 points the series is RANGE-REDUCED — every Nth REAL stored point is returned (never averaged or interpolated) and `reduced` is true. `?granularity=monthly` keeps the LAST real row of each month. Sentinel codes (XX, T1) are served like any cc.

ParamInTypeNotes
cc* path string e.g. EG
from query string ISO prefix lower bound: YYYY, YYYY-MM or YYYY-MM-DD
to query string ISO prefix upper bound (inclusive of the whole prefix)
granularity query string: daily | monthly Granularity of the `daily` series (`alloc` is inherently monthly)

200 History series · 400 Invalid cc / range / granularity · 404 Unknown country

request
curl 'https://api.ipdex.io/v1/country/EG/history?from=2000&granularity=monthly'
200 · response
{
  "cc": "EG",
  "dataVersion": "551c9b9a385b",
  "alloc": [
    {
      "ym": "2024-02",
      "rir": "afrinic",
      "v4_addrs": 256,
      "v6_blocks": 0,
      "asn_count": 1
    },
    {
      "ym": "2024-05",
      "rir": "afrinic",
      "v4_addrs": 1024,
      "v6_blocks": 0,
      "asn_count": 1
    },
    {
      "ym": "2024-08",
      "rir": "afrinic",
      "v4_addrs": 0,
      "v6_blocks": 1,
      "asn_count": 0
    },
    {
      "ym": "2024-09",
      "rir": "afrinic",
      "v4_addrs": 1024,
      "v6_blocks": 0,
      "asn_count": 0
    },
    {
      "ym": "2024-11",
      "rir": "afrinic",
      "v4_addrs": 1024,
      "v6_blocks": 1,
      "asn_count": 1
    },
    {
      "ym": "2025-04",
      "rir": "afrinic",
      "v4_addrs": 1024,
      "v6_blocks": 0,
      "asn_count": 0
    },
    {
      "ym": "2025-06",
      "rir": "afrinic",
      "
  …

GET /v1/asn/{asn}/history

ASN daily stats history (sparse, write-on-change).

Rows are returned AS STORED — SPARSE: an (asn, day) row exists only when a value changed that day. READ CONVENTION (forward-fill): the absence of a row for a day means “unchanged since the latest row with day ≤ that day” — clients carry the last value forward; `sparse: true` marks this. Day-1 of the series (2026-06) is a full population. Same `from`/`to`/`granularity` and 400-point range-reduction semantics as the country endpoint — reduction drops real points, never averages.

ParamInTypeNotes
asn* path string e.g. AS8452
from query string ISO prefix lower bound
to query string ISO prefix upper bound (inclusive of the whole prefix)
granularity query string: daily | monthly

200 Sparse history series · 400 Invalid ASN / range / granularity · 404 Unknown ASN

request
curl https://api.ipdex.io/v1/asn/AS8452/history
200 · response
{
  "asn": 8452,
  "dataVersion": "551c9b9a385b",
  "sparse": true,
  "daily": [
    {
      "day": "2026-06-12",
      "prefix_count": 1718,
      "v4_addrs": 7586304,
      "v6_ranges": 3
    },
    {
      "day": "2026-06-13",
      "prefix_count": 1718,
      "v4_addrs": 7586304,
      "v6_ranges": 3
    }
  ],
  "reduced": false,
  "…": "…more"
}