Ready to connect.
A JSON API for approximate location and autonomous system lookups on IPv4 and IPv6 addresses.
Getting started
- Create your account and verify your email address.
- Generate a key in your dashboard. The complete key is shown only once.
- Send the key in the header of every request.
curl 'https://iplumo.com/api/v1/lookup?ip=8.8.8.8' \
-H 'Authorization: Bearer YOUR_API_KEY'Base URL: https://iplumo.com/api/v1. All dashboard usage dates use UTC.
Authentication
Authorization: Bearer YOUR_API_KEYAn API key is required on Free, Pro and Business. Store it as a server environment variable. Keys in URLs are not accepted. Revoked keys stop authorizing new requests.
The public home page demo supports individual lookups without an account and shares the source IP's free limit. It does not replace authenticated endpoints.
Look up an IP or domain
ip is required. It accepts a public IP or a domain without a protocol or path. Domain lookups use one public address, not all addresses or the website's content.
curl 'https://iplumo.com/api/v1/lookup?ip=example.com&fields=countryCode,city,as,security' -H 'Authorization: Bearer YOUR_API_KEY'{
"status": "success",
"query": "8.8.8.8",
"country": "United States",
"countryCode": "US",
"as": "AS15169 GOOGLE",
"asname": "GOOGLE"
}Fields without data are returned as null. Data may change and does not represent an exact location.
Up to 100 IPs in a batch
curl -X POST 'https://iplumo.com/api/v1/batch' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '["8.8.8.8", "1.1.1.1", "2606:4700:4700::1111"]'The body must be an array of 1 to 100 IPs. Objects with per-item options are also supported:
[
"8.8.8.8",
{
"query": "1.1.1.1",
"fields": "country,as",
"lang": "en"
}
]Results retain input order. Batches accept IPs, not domains. Invalid or private IPs produce a result with status: "fail", without preventing other lookups. Malformed batches or more than 100 items return HTTP 422.
[
{
"status": "success",
"query": "8.8.8.8",
"country": "United States"
},
{
"status": "fail",
"query": "192.168.1.1",
"message": "The IP belongs to a private or reserved range."
}
]Fields and languages
Use ?fields=country,city,as&lang=es to reduce the response. Available languages: es and en; English is the default. Options in each batch item override the URL options.
status and query are always included. Successful responses also retain source, dataUpdatedAt, fetchedAt and attribution, even when selecting fields. Errors also retain message.
| Fields | Description |
|---|---|
status, message, query | Status, error reason and normalized IP. |
continent, continentCode | Continent name and code. |
country, countryCode | Country and two-letter ISO code. |
region, regionName, city, zip | Region, city and postal code, when available. |
lat, lon, accuracyRadius | Approximate location center and accuracy radius in kilometers. |
timezone | IANA time zone. |
source, dataUpdatedAt, fetchedAt, attribution | Record metadata. dataUpdatedAt identifies the local edition; fetchedAt records retrieval. Unknown dates are null. |
district, offset, currency, isp, org | District, UTC offset in seconds, currency, ISP and organization when available. null if unavailable. |
security | Additive object: proxy and hosting mirror their existing indicators. vpn, tor, datacenter and residential_proxy remain null until specific evidence is available. Existing fields are unchanged. |
mobile, proxy, hosting | Network indicators. proxy groups proxies, VPNs and Tor without distinguishing between them. null means unknown, not false. |
as, asname | Autonomous system number and organization. This is not necessarily the user's ISP. |
IPLumo uses stored records and regular updates without mixing locations in a response. Expired results are refreshed through a queue. See sources and frequency. This API does not detect the visitor’s DNS resolver.
Limits and retries
| Plan | Requests/min | Batch/min | IPs/min | Keys |
|---|---|---|---|---|
| Free | 50 | 10 | 1000 | 1 |
| Pro | 1000 | 200 | 20000 | 5 |
| Business | 5000 | 1000 | 100000 | 15 |
No monthly quota. Rolling 60-second window. Keys share the account limit; limits also apply per key and source IP within the plan. A batch of N IPs consumes one request, one batch slot and N IPs. 429 rejections consume no additional capacity. Admitted requests may consume capacity even if the subsequent lookup fails.
| Header | Meaning |
|---|---|
X-RateLimit-Batch-Limit / -Remaining | Maximum and remaining batch capacity (POST batch only). |
X-RateLimit-IP-Limit / -Remaining | Maximum and remaining processed-IP capacity. |
X-RateLimit-Reason | On 429: requests, batch or ips identifies the exhausted limit. |
X-RateLimit-Limit | Maximum requests in 60 seconds. |
X-RateLimit-Remaining / X-Rl | Requests remaining after this call. |
X-Ttl | Retry delay on 429; on admitted requests, 60 seconds until this new request expires. |
X-RateLimit-Reset | Unix timestamp in seconds for that deadline. |
Retry-After | On HTTP 429, seconds to wait before retrying. |
The dashboard combines historical completed lookups with new per-minute/key metrics, including errors and 429 rejections after key authentication. Attempts without a valid key cannot be attributed to an account. Minute metrics are approximate; use API headers for exact rolling-window headroom.
Predictable errors
| HTTP | Reason |
|---|---|
200 | Request processed. In a batch, check each item's status: it may be fail. |
404 | Route or resource not found; an IP without data uses status: fail. |
500 | Unexpected application or infrastructure error. |
400 | Invalid JSON, fields, language or source IP. |
401 | Missing, invalid or revoked key. |
403 | Key paused by plan, denied permission or IP/origin; or unverified account. |
413 | Request body too large (32 KiB maximum for batch). |
415 | The body requires Content-Type: application/json. |
422 | Invalid parameters or batch; private IP in an individual lookup. |
429 | Rate limit reached. Respect Retry-After. |
503 | Service or data temporarily unavailable. |
JavaScript example
// Run this code on your server, never in the browser.
const response = await fetch(
'https://iplumo.com/api/v1/batch?lang=es',
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.IP_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(['8.8.8.8', '1.1.1.1']),
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.message);
}
const results = await response.json();Python
import os
import requests
r = requests.get(
"https://iplumo.com/api/v1/lookup",
params={"ip": "8.8.8.8", "fields": "countryCode,city,as,security"},
headers={"Authorization": "Bearer " + os.environ["IP_API_KEY"]},
timeout=15,
)
r.raise_for_status()
print(r.json())PHP
<?php
$ch = curl_init('https://iplumo.com/api/v1/batch');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('IP_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['8.8.8.8', '1.1.1.1']),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($body === false || $status !== 200) {
throw new RuntimeException('IPLumo request failed: ' . $status);
}
print_r(json_decode($body, true, 512, JSON_THROW_ON_ERROR));
curl_close($ch);Key security
Keep keys on your server. Rename, regenerate, revoke and scope permissions from your dashboard. Business supports IP/CIDR and exact origins (for example https://example.com). An empty list is unrestricted. With an origin list, requests without Origin are rejected. Origin can be forged outside browsers and does not replace authentication; this setting does not enable CORS. Configured restrictions persist on downgrade.
For 429 responses, wait for the duration indicated by Retry-After. For 503 errors, use bounded retries with exponential backoff.