Batch IP Geolocation API
You need to geolocate many IPs at once and detect proxies/VPNs without building your own resolver queue. By the end of this guide you’ll send a single request to a batch endpoint, parse geolocation and security fields, understand credits and limits, and ship a production-safe integration.
What the Batch IP Geolocation endpoint does
The batch endpoint resolves multiple IP addresses in one HTTP POST and returns standardized geolocation plus security signals per IP. This reduces round-trips and improves throughput when you already have a list of IPs to enrich.
Key capabilities:
- IP geolocation: country, region, city, latitude/longitude, timezone, and postal code.
- Network identity: ISP, org, and AS (autonomous system) string.
- Security indicators: proxy, VPN, and cloud provider flags for basic risk filtering.
Endpoint, method, and auth
Endpoint path: /api/batch-ip
Method: POST
Host: https://ipxapi.com
Auth: Authorization: Bearer YOUR_KEY
Request body: a JSON array of IPv4 or IPv6 addresses. The documented fixture is:
["66.165.2.7","190.191.2.241"]
Operational constraints to plan for:
- Max IPs per batch: 1024.
- Credits per request: n + 1 (one overhead credit per batch plus one per IP).
- Content-Type: application/json.
Pricing and trial:
- Basic: $29.99/mo.
- Trial: 7 days or 50 requests.
Reference links: Documentation, MCP, and Register.
Quick start: cURL you can paste
This request uses the official fixture array and Bearer auth. Replace YOUR_KEY with your token.
curl -X POST "https://ipxapi.com/api/batch-ip" -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" -d '["66.165.2.7","190.191.2.241"]'
Official JSON sample
This is the official example response from the docs (the first row’s query may differ from the cURL body in fixtures). Use these exact field names when parsing.
{
"results": [
{
"status": "success",
"country": "United States",
"countryCode": "US",
"region": "US-CA",
"regionName": "California",
"city": "Mountain View",
"zip": "94043",
"lat": 37.40599,
"lon": -122.0786,
"timezone": "America/Los_Angeles",
"isp": "MailChimp",
"org": "MailChimp",
"as": "AS14782 MailChimp",
"query": "148.105.12.120",
"security": {
"is_proxy": false,
"is_vpn": false,
"is_cloud_provider": true
}
}
]
}
What you’ll typically use:
- status: success or failure indicator per IP.
- country, countryCode, region/regionName, city, zip: human-friendly location fields.
- lat, lon: decimal degrees; pair with your map or distance logic.
- timezone: IANA name (e.g., America/Los_Angeles) for localizing timestamps.
- isp, org, as: network owner context and ASN label for rules and analytics.
- query: the IP resolved for the row.
- security: booleans for is_proxy, is_vpn, is_cloud_provider to gate risky traffic.
JavaScript example: POST /api/batch-ip and parse results
This snippet posts the documented fixture list, checks the HTTP status, and reads a few core fields from each result. Keep the same endpoint and field names in your code.
import fetch from "node-fetch";
async function batchGeolocate() {
const url = "https://ipxapi.com/api/batch-ip";
const ips = ["66.165.2.7", "190.191.2.241"];
const resp = await fetch(url, {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify(ips),
// Consider setting a timeout in your HTTP client of choice.
});
if (!resp.ok) {
// Surface HTTP transport errors. The API returns per-IP status in the body too.
const text = await resp.text();
throw new Error(`Request failed: ${resp.status} ${resp.statusText} - ${text}`);
}
const data = await resp.json();
if (!data || !Array.isArray(data.results)) {
throw new Error("Unexpected response shape: missing results array");
}
// Map to a smaller shape your app needs.
const mapped = data.results.map((row) => ({
ip: row.query,
status: row.status,
country: row.country,
region: row.region,
city: row.city,
lat: row.lat,
lon: row.lon,
timezone: row.timezone,
isp: row.isp,
asn: row.as,
security: row.security
}));
// Example: filter out VPN/proxy/cloud-provider traffic quickly.
const filtered = mapped.filter((r) => {
const s = r.security || {};
return !(s.is_proxy || s.is_vpn || s.is_cloud_provider);
});
return { all: mapped, filtered };
}
batchGeolocate()
.then(({ all, filtered }) => {
console.log("Resolved:", all.length, "IPs");
console.log("Allowed after security filter:", filtered.length);
// Example output for the first record:
if (all[0]) {
const r = all[0];
console.log(`IP ${r.ip} - ${r.city}, ${r.region}, ${r.country} [${r.timezone}]`);
}
})
.catch((err) => {
console.error("Batch geolocation error:", err);
});
Designing your batch workflow
Use batching when you already have a list of IPs (e.g., log enrichment, ETL, risk scans) and want to reduce request overhead. For interactive, one-off lookups, a single-IP endpoint may be more natural; for background jobs, batches reduce connection churn.
Batch sizing
Group IPs up to the documented maximum of 1024 per request. A balanced approach is to send batches in the hundreds to keep response sizes manageable and improve failure isolation.
Queueing and retries
Push IPs into a queue and flush in batches. If the HTTP request fails, retry the whole batch with exponential backoff. If the HTTP request succeeds but individual rows have a non-success status, record and optionally retry those IPs separately later.
Interpreting geolocation and security results
Country and region strings support policy logic (e.g., content licensing or tax estimation). Use timezone to convert event times for users; it’s an IANA name suitable for common timezone libraries. Latitude/longitude are decimal degrees you can feed to mapping or distance formulas.
ISP, org, and AS are useful for network segmentation and analytics. For example, you may down-rank traffic from known cloud providers if your risk model treats those as headless or automated sources. The security flags let you quickly allowlist or blocklist at the edge without maintaining your own provider/IP lists.
Credits, rate planning, and cost awareness
Each batch costs n + 1 credits (n is the number of IPs). When you plan your throughput, calculate daily and hourly ceilings with this formula in mind, then group IPs efficiently to reduce overhead credits per item.
Basic plan is $29.99/mo. The trial allows 7 days or 50 requests. You can register and see your usage metrics in the dashboard, then size your batches according to your ingestion volumes.
Caching and data freshness
Cache results for IPs you see repeatedly to cut costs and latency. A simple in-memory or Redis cache keyed by IP works well for application servers. For long-running analytics jobs, persist enriched results as part of your pipeline outputs.
Timezones and political boundaries change infrequently, but ISP/ASN ownership can shift. Implement a cache TTL that fits your use case; for user-facing sessions, many teams cache for hours to a day, while ETL pipelines may cache for days. If you rely on security flags for critical gating, consider a shorter TTL.
Error handling and validation
Transport layer: Handle non-2xx HTTP responses by logging the payload for diagnostics and retrying with backoff. Network errors should be retried with jitter to avoid thundering herds.
Per-IP status: Always check the status field for each result row. Only treat rows with status equal to success as valid. For other statuses, store them for investigation or down-route them in your application.
Input validation: Strip whitespace, deduplicate IPs in the batch, and ensure your JSON array contains only strings formatted as IP addresses before sending.
Performance tips
- Use HTTP keep-alive to avoid reconnect costs between batches.
- Run requests concurrently but cap parallelism so you don’t overload your app or hit account-level ceilings.
- Stream logs and metrics: count successes vs. per-IP failures, average latency per batch, and effective credits per item (n+1 amortization).
- Right-size your JSON parser limits since a 1024-row response can be large.
Testing and tooling
You can exercise your integration from your own scripts or via the MCP environment for connectivity verification and quick inspection. Keep the Authorization header in every call you make in test and production.
Security and compliance considerations
Store only the fields you need. If you log raw responses, redact Authorization headers and any sensitive internal identifiers. If you build access policies based on country or region, document those decisions for audits and keep your cache refresh policy clear and consistent.
Operational checklist
- Authentication: Bearer YOUR_KEY set on every request.
- Endpoint: POST https://ipxapi.com/api/batch-ip with a JSON array body.
- Batch size: up to 1024 IPs; plan credits using n + 1.
- Parsing: read status; only trust rows with success.
- Core fields: country/countryCode, region/regionName, city, zip, lat, lon, timezone, isp, org, as, query, security flags.
- Caching: set TTLs aligned with your security and freshness needs.
- Retries: backoff on transport errors; isolate per-IP failures.
FAQ
How many IPs can I send in one batch?
Up to 1024 IPs per POST to /api/batch-ip.
How are credits calculated for a batch?
Credits are n + 1, where n is the number of IPs in the array and there is one overhead credit per batch.
What authentication is required?
Include Authorization: Bearer YOUR_KEY in the request headers for every call.
Which fields should I rely on for time localization?
Use timezone, which is an IANA identifier (for example, America/Los_Angeles). Convert timestamps server-side or in your client using this value.
Can I detect VPNs and proxies?
Yes. Use the boolean fields in security: is_proxy, is_vpn, and is_cloud_provider to gate or flag traffic.
Get started
Create your key, send the batch fixture, and plug the results into your application. Use the Register link to open an account (trial: 7 days or 50 requests; Basic is $29.99/mo), then keep the Documentation handy while you wire up /api/batch-ip and deploy.
