Batch
Answers up to 1000 addresses in one call. Each distinct string in ips
is one lookup: it costs exactly what GET /{ip} costs for that address
and comes back with exactly the fields that call would carry for your
plan. Exact duplicates collapse to one entry and one lookup.
Both maps in the answer are keyed by the string you sent, so nothing has
to be lined up by position; the ip inside each result is the
normalized form. An address that could not be answered sits in errors
with the status and message the single lookup would have given, and
never disturbs the others: a string that is not an address is a 400
there, and an overage cap reached part way through leaves the remaining
entries as 429s.
The call itself fails only for the reasons below, and a 429 on the
call always carries Retry-After: the batch is admitted or refused
whole by the rate limit, so a per-entry 429 is always the overage cap
and never a throttle.
A batch needs a paid plan: without a key the call is refused with 401,
and with a key on the free plan with 402, unless it names one address,
which is answered as GET /{ip} would answer it, under the same rate
limit. Unlimited looks up one address at a time.
Authorization
apiKeyQueryapikey in query
?apikey=<key>. Convenient in a browser; prefer a header elsewhere.
apiKeyHeaderX-Api-Key in header
X-Api-Key: <key>.
bearerAuthbearer token
Authorization: Bearer <key>.
Request body
application/json
ipsrequiredarray<string>The addresses to classify, 1 to 1000 per call, counted before duplicates collapse. Each distinct string is one lookup.
Example ["1.1.1.1","2606:4700:4700::1111"]
Responses
200application/json
One entry per distinct input string, in results or in errors.
Present fields within a result are those your plan includes; see the
tier table in the API description.
resultsrequiredobjectOne answer per input string that was classified, keyed by the string
as you sent it; the ip inside is the normalized form. Each value is
exactly what GET /{ip} answers for your plan.
errorsrequiredobjectOne entry per input string that could not be classified, keyed the same way. Empty when every entry was answered.
TypeScript type
{
results: Record<string, {
ip: string;
is_vpn: boolean;
is_hosting?: boolean;
is_relay?: boolean;
is_tor?: boolean;
is_cdn?: boolean;
is_resproxy?: boolean;
is_dcproxy?: boolean;
is_mobproxy?: boolean;
is_pubproxy?: boolean;
vpn?: {
provider?: string;
last_seen?: string;
confidence?: string;
method?: string;
};
hosting?: {
provider?: string;
confidence?: string;
last_seen?: string;
};
relay?: {
provider?: string;
confidence?: string;
last_seen?: string;
};
tor?: {
provider?: string;
confidence?: string;
last_seen?: string;
};
cdn?: {
provider?: string;
confidence?: string;
last_seen?: string;
};
resproxy?: {
provider?: string;
first_seen?: string;
last_seen?: string;
hits?: number;
hits_days_pct?: number;
providers_num?: number;
};
dcproxy?: {
provider?: string;
first_seen?: string;
last_seen?: string;
hits?: number;
hits_days_pct?: number;
providers_num?: number;
};
mobproxy?: {
provider?: string;
first_seen?: string;
last_seen?: string;
hits?: number;
hits_days_pct?: number;
providers_num?: number;
};
pubproxy?: {
entry?: boolean;
exit?: boolean;
protocols?: string[];
num_ports?: number;
num_proxies?: number;
last_seen?: string;
last_usable?: string;
};
location?: {
continent: string;
continent_name: string;
country: string;
country_name: string;
timezone: string;
currency_code: string;
currency_name: string;
currency_symbol: string;
flag_emoji: string;
flag_unicode: string;
};
asn?: {
asn: number;
name: string;
domain: string;
type: string;
prefix: string;
};
trial_expired?: boolean;
}>;
errors: Record<string, {
status: number;
error: string;
}>;
}400application/json
The body is not a batch, or names too few or too many addresses.
errorrequiredstringA human-readable explanation of the failure.
Example not a valid IP address
TypeScript type
{
error: string;
}401application/json
No API key was presented for more than one address, or the one presented is unknown, revoked, or expired.
errorrequiredstringA human-readable explanation of the failure.
Example not a valid IP address
TypeScript type
{
error: string;
}402application/json
The key is on the free plan and the batch names more than one address: a batch needs a paid plan.
errorrequiredstringA human-readable explanation of the failure.
Example not a valid IP address
TypeScript type
{
error: string;
}403application/json
The key restricts which source addresses may use it and this request came from none of them, or the key was sent over plain HTTP, where anyone on the network path could read it. Rotate a key that was.
errorrequiredstringA human-readable explanation of the failure.
Example not a valid IP address
TypeScript type
{
error: string;
}413application/json
The body is larger than any batch of 1000 addresses can be.
errorrequiredstringA human-readable explanation of the failure.
Example not a valid IP address
TypeScript type
{
error: string;
}429application/json
The rate limit refused the whole call. Always transient and always
with Retry-After; a reached overage cap is reported per entry in a
200 instead.
errorrequiredstringA human-readable explanation of the failure.
Example not a valid IP address
TypeScript type
{
error: string;
}