Docs

Batch lookups

Need to check many IPs at once? POST /v1/check/batch takes a list of IPs and returns the same per-IP payload as single /v1/check — one round trip instead of many.

POST https://api.geoq.io/v1/check/batch

Request body

Send JSON with an ips array. Maximum 100 IPs per call. Mixed IPv4 and IPv6 is fine.

{ "ips": ["1.2.3.4", "2001:4860:4860::8888"] }

Headers

HeaderValue
x-api-key<api_key> — required (see auth).
Content-Typeapplication/json

Examples

$ curl "https://api.geoq.io/v1/check/batch" \
    -H "x-api-key: $GEOQ_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"ips":["8.8.8.8","2001:4860:4860::8888"]}'
const res = await fetch("https://api.geoq.io/v1/check/batch", {
  method: "POST",
  headers: {
    "x-api-key": process.env.GEOQ_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ ips: ["8.8.8.8", "2001:4860:4860::8888"] }),
});

const { count, results } = await res.json();
for (const r of results) {
  if (r.error) console.warn(r.ip, r.error);
  else console.log(r.ip, r.risk.score, r.risk.level);
}
import os, requests

res = requests.post(
    "https://api.geoq.io/v1/check/batch",
    headers={"x-api-key": os.environ["GEOQ_API_KEY"]},
    json={"ips": ["8.8.8.8", "2001:4860:4860::8888"]},
)

body = res.json()
for r in body["results"]:
    if "error" in r:
        print(r["ip"], r["error"])
    else:
        print(r["ip"], r["risk"]["score"], r["risk"]["level"])

Response

A 200 OK returns count (number of results) and a results array. Each entry is either a full per-IP payload — identical to the single-lookup response schema — or, for an unparseable entry, an error object:

{ "ip": "not-an-ip", "error": "invalid_ip" }

Invalid entries do not fail the whole request — they come back inline so you can match results to inputs by position.

{
  "count": 2,
  "results": [
    {
      "ip": "8.8.8.8",
      "version": 4,
      "geo": {
        "country": "United States",
        "country_code": "US",
        "region": "California",
        "city": "Mountain View",
        "latitude": 37.4,
        "longitude": -122.1,
        "timezone": "America/Los_Angeles"
      },
      "network": {
        "asn": 15169,
        "as_org": "Google LLC",
        "is_announced": true,
        "is_bogon": false,
        "rpki": "valid",
        "allocation_date": "2000-03-30",
        "allocation_age_days": 9566,
        "registration_country": "US"
      },
      "signals": {
        "connection_type": "datacenter",
        "datacenter_provider": "gcp",
        "relay_provider": null,
        "is_relay": false,
        "is_tor": false,
        "is_vpn": false,
        "is_proxy": false,
        "is_public_resolver": true,
        "is_drop_listed": false,
        "recent_abuse": false,
        "is_verified_bot": false,
        "verified_bot_name": null
      },
      "evidence": {
        "connection_type": "authoritative",
        "tor": "authoritative",
        "vpn": "inferred",
        "proxy": "beta",
        "verified_bot": "authoritative",
        "relay": "authoritative",
        "routing": "authoritative",
        "allocation": "authoritative",
        "drop_listed": "authoritative",
        "recent_abuse": "beta",
        "public_resolver": "authoritative"
      },
      "risk": {
        "score": 20,
        "level": "low",
        "reasons": [
          "connection_type:datacenter",
          "benign_network_kind"
        ]
      },
      "attribution": "https://geoq.io/attributions"
    },
    {
      "ip": "not-an-ip",
      "error": "invalid_ip"
    }
  ]
}

Quota & limits

  • Batch lookups count toward your plan quota, metered per IP — a batch of 50 IPs counts as 50 lookups.
  • Each IP in a batch counts as one lookup against your quota — a batch of 50 counts as 50. Where a count is ever ambiguous, we round in your favour.
  • Up to 100 IPs per call. Send more than that and the request is rejected with 400.
  • When you exceed your quota, the endpoint returns 429 with a quota message — see rate limits.

Status codes

CodeMeaning
200Success — results returned (individual entries may carry error).
400Malformed body, missing ips, or more than 100 IPs.
401Missing or invalid API key.
429Quota / rate limit exceeded — see rate limits.
5xxServer error — retry with backoff.

Full error format on the errors page.