If you've ever needed to geolocate a list of IP addresses - whether from server logs, signup events, or security alerts - you know how tedious it is to loop through them one by one. That's why we built the Batch IP Geolocation API: a single endpoint that resolves up to 100 IPs in one request.
Why Use the Batch API?
- Fewer round trips. Instead of 100 individual API calls, send one request and get all results back at once.
- Automatic deduplication. If your list contains duplicate IPs, we detect them, look each one up only once, and count it against your quota only once.
- Parallel processing. All IPs in a batch are resolved concurrently on our servers, so response times stay low even for large batches.
- Per-IP error handling. If one IP fails (e.g., a private address with no WHOIS data), the rest still succeed - you get individual error details alongside successful results.
Making a Batch Request
Send a POST request to the batch endpoint with a JSON body containing an array of IP addresses:
curl -X POST "https://api.theipapi.com/v1/ip/batch?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"ips": ["8.8.8.8", "1.1.1.1"]}'
Response Format
The response is a JSON object with a results map keyed by IP address. Each value follows the same format as our single-IP endpoint:
{
"status": "OK",
"results": {
"8.8.8.8": {
"status": "OK",
"body": {
"ip": "8.8.8.8",
"location": {
"city": "Mountain View",
"region": "California",
"country": "United States of America",
"country_code": "US",
"latitude": 37.405992,
"longitude": -122.078515,
"timezone": "America/Los_Angeles"
},
"asn": {
"asn": 15169,
"asn_description": "GOOGLE - Google LLC, US",
"org_name": "Google LLC",
"country": "US",
"rir": "ARIN",
"created": "2005-11-23",
"updated": "2019-10-31",
"network": "8.8.8.0/24"
},
"company": {
"name": "Google LLC",
"address": "1600 Amphitheatre Parkway, Mountain View, CA, US",
"network": "8.8.8.0 - 8.8.8.255",
"route": "8.8.8.0/24"
},
"is_bogon": false,
"is_datacenter": true,
"is_vpn": false
},
"response_time_ms": 5
},
"1.1.1.1": {
"status": "OK",
"body": {
"ip": "1.1.1.1",
"location": {
"city": "Los Angeles",
"region": "California",
"country": "United States of America",
"country_code": "US",
"latitude": 34.052571,
"longitude": -118.243907,
"timezone": "America/Los_Angeles"
},
"asn": {
"asn": 13335,
"asn_description": "CLOUDFLARENET - Cloudflare, Inc., US",
"org_name": "Cloudflare, Inc.",
"country": "AU",
"rir": "ARIN",
"created": "2010-07-15",
"updated": "2021-07-01",
"network": "1.1.1.0/24"
},
"company": {
"name": "APNIC and Cloudflare DNS Resolver project",
"address": "101 Townsend Street, San Francisco, CA, US",
"network": "1.1.1.0 - 1.1.1.255",
"route": "1.1.1.0/24"
},
"is_bogon": false,
"is_datacenter": false,
"is_vpn": false
},
"response_time_ms": 5
}
},
"total_ips": 2,
"response_time_ms": 42
}
Each result includes the full geolocation payload - location, ASN, company info, and flags for VPN, datacenter, and bogon detection - exactly as you'd get from the single-IP endpoint.
Limits and Quota
- Maximum batch size: 100 IPs per request.
- Quota is all-or-nothing. If your remaining quota can't cover all unique IPs in the batch, the entire request is rejected with HTTP 429. This prevents partial charges and makes retry logic straightforward.
- Deduplication saves quota. Sending the same IP multiple times in one batch only counts once.
Error Handling
Request-level errors return immediately with an appropriate HTTP status:
| Status | Reason |
|---|---|
| 400 | Empty IP list, invalid IP, or batch exceeds 100 |
| 401 | Missing or invalid API key |
| 405 | Non-POST method |
| 429 | Rate limit or quota exceeded |
Per-IP errors appear inside the results map without affecting other IPs:
{
"status": "OK",
"results": {
"8.8.8.8": {
"status": "OK",
"body": { ... },
"response_time_ms": 5
},
"192.168.1.1": {
"status": "Error",
"error": "No geolocation data found"
}
},
"total_ips": 2,
"response_time_ms": 15
}
Example: Python
import requests
url = "https://api.theipapi.com/v1/ip/batch"
params = {"api_key": "YOUR_API_KEY"}
payload = {
"ips": ["8.8.8.8", "1.1.1.1", "9.9.9.9"]
}
response = requests.post(url, params=params, json=payload)
if response.status_code == 200:
data = response.json()
for ip, result in data["results"].items():
if result["status"] == "OK":
loc = result["body"]["location"]
print(f"{ip}: {loc['city']}, {loc['country']}")
else:
print(f"{ip}: Error - {result['error']}")
else:
print(f"Request failed: {response.status_code}")
Example: Node.js
const response = await fetch(
"https://api.theipapi.com/v1/ip/batch?api_key=YOUR_API_KEY",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
ips: ["8.8.8.8", "1.1.1.1", "9.9.9.9"],
}),
}
);
const data = await response.json();
for (const [ip, result] of Object.entries(data.results)) {
if (result.status === "OK") {
const { city, country } = result.body.location;
console.log(`${ip}: ${city}, ${country}`);
} else {
console.log(`${ip}: Error - ${result.error}`);
}
}
When to Use Batch vs. Single IP
| Use case | Recommended endpoint |
|---|---|
| Real-time lookup on page load | Single IP (GET /v1/ip/{ip}) |
| Processing log files or CSV exports | Batch (POST /v1/ip/batch) |
| Enriching signup/order events in bulk | Batch |
| Webhook-triggered single-IP enrichment | Single IP |
Get Started
The Batch API is available on all plans - free and paid. Sign up to get your API key and start resolving IPs in bulk today. If you have questions, reach out to us.
Happy batching!