Product · IP Lookup API

One endpoint. Every IP question answered.

Call /json/{ip} and get country, region, city, postal, latitude, longitude, timezone, ASN, organisation, datacenter and VPN detection. In one response. On every plan.

What you get in one call

curl https://api.ip-atlas.io/json/8.8.8.8
{
  "ip": "8.8.8.8",
  "country": "US",
  "country_name": "United States",
  "registry": "arin",
  "asn": 15169,
  "org": "GOOGLE",
  "is_datacenter": true,
  "is_vpn": false
}

The same endpoint accepts IPv6 and a second, authenticated variant (GET /json, no IP in path) returns data about the caller's own source address — picked from CF-Connecting-IP, X-Real-IP, or X-Forwarded-For.

Why not build this yourself?

  • Pulling 5 × RIR daily delegation files, reconciling them into an authoritative IPv4 prefix table: ~4 hours/week ongoing.
  • Keeping a curated list of datacenter and VPN ranges (~50 providers) accurate: another ~4 hours/week, forever.
  • Serving lookups in <20 ms: requires a sorted prefix array in memory, atomic reload on refresh, and a tuned Go binary.
  • We do this work once, for everyone — see pricing.

Authentication & quotas

Pass your key in the X-API-Key header. Every response carries X-RateLimit-Limit-Month, X-RateLimit-Remaining-Month, and — when overage is charged — X-Overage-Charged-Cents. 429s carry Retry-After. The whole contract is in the API reference. See pricing for the full plan comparison.

Batch endpoint — enrich 100 IPs per round trip

POST /v1/batch takes an ordered array of up to 100 IPs per call and returns results in the same order, with per-IP error objects for the ones that don't parse. One authenticated call performs one atomic quota preflight — if charging n IPs would exceed your monthly quota (and overage is disabled or capped), the call returns 429 with no partial results. You never pay for half a batch.

Request

curl -X POST https://api.ip-atlas.io/v1/batch \
  -H "X-API-Key: ipa_live_..." \
  -H "Content-Type: application/json" \
  -d '{"ips":["8.8.8.8","1.1.1.1","not-an-ip"]}'

Response

{
  "results": [
    {"ip":"8.8.8.8","country":"US","asn":15169, ...},
    {"ip":"1.1.1.1","country":"AU","asn":13335, ...},
    {"ip":"not-an-ip","error":"invalid IP address"}
  ]
}

Semantics you can rely on

  • Order-preserving. results[i] corresponds to ips[i].
  • Atomic quota preflight. If charging n IPs would exceed your monthly quota and overage is disabled/capped, the call returns 429 with no partial results.
  • Each IP = 1 request against your monthly quota (and against any overage meter).
  • Per-IP errors are inline. Only request-level errors (invalid key, over quota) return as HTTP 4xx/5xx.
  • Cap is 100 IPs per call. Need more? Page through with 100-item batches — they're individually billed against your quota, not multiplied.

When to use it

Log enrichment

Append geo/ASN to every line of yesterday's access log. 1M lines = 10,000 batch calls.

Bulk user analysis

Resolve thousands of signup IPs during a fraud review without 10,000 individual RTTs.

Migration / backfill

Moving off another IP API? Enrich your historical data in big batches with clean rate limiting.

Node example

import { IPAtlas } from '@trellisdigitalservices/ip-atlas';
const c = new IPAtlas({ apiKey: 'ipa_live_...' });

// Read IPs from a file, chunk, enrich, write.
const chunks = chunk(ips, 100);
for (const c100 of chunks) {
  const batch = await c.lookupBatch(c100);
  for (const r of batch.results) { /* ... */ }
}

Full reference: Batch API in the docs.