ReferenceBulk Lookup
Bulk Lookup
Locates up to 100 addresses in one request. Results come back in request order, with an error in place of each address that could not be located.
POST
/v1/lookupRequest
| Parameter | In | Description |
|---|---|---|
ips | body | Array of 1 to limits.bulk_max_ips (100) address strings. Other fields are rejected. |
lang | query | Language of place names, as for Lookup. |
Content-Type | header | Must be application/json. |
curl -H "X-API-Key: $LOCATE_ME_KEY" \
-H "Content-Type: application/json" \
-d '{"ips": ["1.1.1.1", "192.168.0.1", "bogus"]}' \
http://localhost:8080/v1/lookup
const res = await fetch("http://localhost:8080/v1/lookup", {
method: "POST",
headers: {
"X-API-Key": process.env.LOCATE_ME_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ ips: ["1.1.1.1", "192.168.0.1", "bogus"] }),
});
const { results } = await res.json();
for (const r of results) console.log(r.ip, r.error ?? r.country?.code);
import os
import requests
res = requests.post(
"http://localhost:8080/v1/lookup",
json={"ips": ["1.1.1.1", "192.168.0.1", "bogus"]},
headers={"X-API-Key": os.environ["LOCATE_ME_KEY"]},
timeout=5,
)
res.raise_for_status()
for r in res.json()["results"]:
print(r["ip"], r.get("error") or r["country"]["code"])
The request body may be at most server.max_body_bytes (256 KiB).
Response
{
"results": [
{
"ip": "1.1.1.1",
"network": "1.1.1.0/24",
"continent": { "code": "OC", "name": "Oceania" },
"country": { "code": "AU", "name": "Australia", "in_eu": false },
"region": { "name": "New South Wales" },
"city": "Sydney",
"location": { "latitude": -33.8688, "longitude": 151.209 }
},
{ "ip": "192.168.0.1", "error": "reserved_address" },
{ "ip": "bogus", "error": "invalid_ip" }
]
}
Each entry of results is either a location, shaped exactly like a Lookup response, or an {"ip", "error"} pair. Tell them apart by the presence of error. In an error pair, ip repeats the string as you sent it.
| Entry error | Meaning |
|---|---|
invalid_ip | Not a valid IPv4 or IPv6 address. |
reserved_address | A private or reserved range, which never has a location. |
not_found | The database has no location for the address. |
Cost
Every address costs one rate-limit unit, invalid ones included. One unit is charged before the body is read, so malformed requests are not free; the rest is charged once the batch size is known.
- A batch larger than the key's burst can never be admitted. It fails at once with
429 exceeds_burst; split it. - A batch that fits the burst but not the units left fails with
429 rate_limitedand aRetry-After.
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_body | The body is not {"ips": [...]}: bad JSON, a wrong type or an unknown field. |
| 400 | invalid_lang | lang is not supported. |
| 401 | unauthorized | Missing, unknown or disabled key. |
| 413 | payload_too_large | The body is larger than server.max_body_bytes. |
| 415 | unsupported_media_type | Content-Type is not application/json. |
| 422 | empty_batch | ips is empty. |
| 422 | batch_too_large | More than limits.bulk_max_ips addresses. |
| 429 | exceeds_burst | The batch costs more than the key's burst. |
| 429 | rate_limited | Not enough units left; wait Retry-After seconds. |