Skip to main content
GET
Look up a single IP
Pass the IP as the ipAddress query parameter, the way every WhoisXML API takes its input:
The path form GET /api/v1/ip/{ip} is still supported and returns the same response.

Authorizations

apiKey
string
query
required

Your API key, passed as the apiKey query parameter on every request. A key sent in a header (Authorization or X-API-Key) is not accepted and gets 401.

Query Parameters

ipAddress
string
required

IPv4 or IPv6 address to classify. Omitting it returns 400 missing_ip_address.

outputFormat
string

Response format. JSON only.

as_of
string<date>

Answer for a past day instead of now: a UTC calendar day written YYYY-MM-DD, for example 2026-09-01. Business and Enterprise only; other plans get 403. The answer is built from that day's archived data under today's data-handling and attribution rules, and its body is IpAsOfResponse, not IpLookupResponse. The archive starts on 2026-07-31 and gains a day each day. Errors: 400 invalid_as_of when the value is not a calendar day; 400 as_of_outside_coverage when the archive holds no such day, with first_day and last_day in the error; 503 as_of_warming, with Retry-After, while that day is being prepared (retry in a minute); 503 as_of_over_budget or as_of_unavailable when the lookup cannot be served right now. A successful answer uses one lookup credit; errors use none.

Response

Successful Response

The result of one IP lookup. Every key listed here is returned on every plan unless its description says otherwise. Most fields above your plan stay in the response with null, or false for the two residential proxy sub-flags; the few that are left out instead say so in their descriptions. Gate on your plan rather than on whether a key is present. x-min-plan names the lowest plan that fills each field. intro means every plan; the free sign-up lookups get the same fields as Intro. The API covers IPv4 today. IPv6 addresses are accepted but currently return little or no classification. The API refreshes once a day.

ip
string
required

The IP address you looked up, in canonical form.

network
string | null
required

The classified network, in CIDR notation, that contains the IP. It can be a single address (a /32). Null when nothing matched, when the label comes from our sightings of this address as a residential proxy exit rather than from a listed network, or when the label is inferred from the ASN alone with no listed range behind it (source is then asn_classification).

classification
string
required

The winning label for the IP, for example vpn, commercial_vpn, corporate_vpn, proxy, datacenter_proxy, residential_proxy, tor, relay, hosting or cdn. unknown means we hold no label for the IP: treat it as no data, not as clean. suspected_vpn and vpn_suspect are advisory and set no boolean flag. On Starter and up, a hosting address can be relabelled proxy because of its ASN's abuse profile (see asn_abuse_promoted).

provider
string | null
required

The named operator of the IP, where we have attributed one: a VPN service, proxy network, privacy relay, CDN, hosting provider or the Tor network. Residential proxy exits are attributed by name on a subset only, so provider can be null on every plan. Starter and up, and Pro and up when the classification is a residential proxy label; below that plan the key is present with null. For a residential proxy address it can name several networks, separated by a comma and a space.

confidence
number | null
required

How sure we are of the classification, from 0 to 1. 0 when the classification is unknown. Pro and up; below Pro the key is present with null.

Required range: 0 <= x <= 1
source
enum<string> | null
required

How the winning label was detected, as one value from a fixed list of method names. Null when the IP has no classification.

Available options:
port_scan,
proxy_enum,
netflow_analysis,
asn_classification,
ct_log,
rdns_cdn,
ptr_resolution,
public_list,
partner_feed,
dns_enumeration,
appliance_probe,
other,
null
detection_method
enum<string> | null
required

The same value as source.

Available options:
port_scan,
proxy_enum,
netflow_analysis,
asn_classification,
ct_log,
rdns_cdn,
ptr_resolution,
public_list,
partner_feed,
dns_enumeration,
appliance_probe,
other,
null
first_seen
string<date-time> | null
required

When the winning label was first recorded for the IP or its range, in ISO 8601. Null when the classification is unknown, or when the label is inferred from the ASN alone with no listed range behind it (network is then null too). Pro and up; below Pro the key is present with null.

last_seen
string<date-time> | null
required

When the winning label was last confirmed for the IP or its range, in ISO 8601. Null when the classification is unknown, or when the label is inferred from the ASN alone with no listed range behind it (network is then null too). Pro and up; below Pro the key is present with null.

observation_count
integer | null
required

How many times we observed this exact address as a residential proxy exit over the trailing 90 days. An address we have not seen in that window keeps its last count. 0 unless the label comes from our sightings of the address itself (network is then null); a label from a listed network, a single-address /32 included, gives 0. Pro and up; below Pro the key is present with null.

Required range: x >= 0
hits_days_pct
number | null
required

Percentage of the trailing 90 days on which the address was seen at least once, from 0 to 100. Null unless the label comes from our sightings of the address itself (network is then null); a label from a listed network, a single-address /32 included, gives null. Pro and up; below Pro the key is present with null.

Required range: 0 <= x <= 100
providers_num
integer | null
required

How many distinct residential proxy networks the address was seen on over about the last 90 days. The count is rebuilt weekly, so a network can stay counted for up to a week after its last sighting leaves that window, and an address we have not seen at all in that window keeps its last count. 0 unless the label comes from our sightings of the address itself (network is then null); a label from a listed network, a single-address /32 included, gives 0. Pro and up; below Pro the key is present with null.

Required range: x >= 0
confidence_decay
number | null
required

A score for a residential proxy address that combines how recently, how often and on how many networks it was seen. It runs from 0 to 1.5 and falls as the last sighting ages. 0 unless the label comes from our sightings of the address itself (network is then null); a label from a listed network, a single-address /32 included, gives 0. Pro and up; below Pro the key is present with null.

Required range: 0 <= x <= 1.5
freshness_class
enum<string> | null
required

The age of last_seen as a bucket: current (less than 2 days old), recent (less than 8 days), stale (less than 91 days) or frozen (91 days or older, or never seen). Pro and up; below Pro the key is present with null.

Available options:
current,
recent,
stale,
frozen,
null
is_vpn
boolean
required

True for a confirmed VPN label: vpn, commercial_vpn, corporate_vpn, vpn_hosting or the retired vpn_concentrator. Suspected VPN labels leave it false.

is_proxy
boolean
required

True when the classification is proxy, datacenter_proxy, mobile_proxy or suspected_proxy. Residential proxy labels set is_residential_proxy instead.

is_tor
boolean
required

True when the classification is tor.

is_relay
boolean
required

True when the classification is relay, a privacy relay such as iCloud Private Relay.

is_hosting
boolean
required

True when the classification is hosting.

is_cdn
boolean
required

True when the classification is cdn.

is_residential_proxy
boolean
required

True for any residential proxy label: residential_proxy, residential_proxy_gateway, residential_proxy_likely or residential_proxy_mobile.

is_residential_proxy_high_confidence
boolean
required

True when the classification is residential_proxy itself, not its gateway, likely or mobile variant. Pro and up; below Pro the key is present with false.

is_residential_proxy_mobile
boolean
required

True when the classification is residential_proxy_mobile. Pro and up; below Pro the key is present with false.

is_open_proxy
boolean
required

True when the winning label comes from a public open proxy list. When a more specific label wins, for example residential_proxy or tor, it is false even if the IP is also on such a list.

is_corporate_vpn
boolean
required

True when the classification is corporate_vpn, a company VPN appliance. is_vpn is true as well.

infra_type
enum<string> | null
required

The kind of network the IP sits on. It comes from the label when the label implies one, and otherwise from the ASN that announces the IP. Every residential proxy label gives residential. mobile comes only from the mobile_proxy label, which has not been assigned since 2026-05-02, and no ASN is classed as a mobile carrier today, so infra_type does not mark mobile networks. Null when neither says.

Available options:
datacenter,
residential,
mobile,
null
risk_score
integer
required

Risk score from 0 to 100, based on the classification and its confidence. Returned on every plan, Intro included. A residential proxy hit scores by how recently we saw the address, in the freshness_class buckets (the bucket itself is shown from Pro): current 95-100, recent 75-85, stale 45-60, frozen 25-35. Within a bucket, an address seen on more days and through more networks scores higher. A VPN, proxy, threat-list or hosting match on the same address keeps the score it would have on its own, so the band never lowers it. On a mobile carrier, satellite network or secure web gateway that we list as shared by many people, a residential proxy hit scores at most 60 whatever its recency and carries the SHARED_ADDRESS_NETWORK reason: step it up, with a challenge or a review, rather than block it. The list does not yet cover every such network. On Starter and up, the score for a hosting address also reflects its ASN's abuse profile (see hosting_risk_calibrated). The score is not a probability.

Required range: 0 <= x <= 100
asn
integer | null
required

The autonomous system number that announces the IP. Null when unknown.

asn_org
string | null
required

The name of the organization that holds that ASN. Null when unknown.

netblock
string | null
required

The most specific registered network block that contains the IP, as its first and last address joined by a hyphen, for example 8.8.8.0-8.8.8.255. It is a range, not CIDR notation: a registered block need not fall on a CIDR boundary. Null when no registered block is known. Starter and up; below Starter (Intro and the free sign-up lookups) the key is present with null.

netname
string | null
required

The registry's name for that block. Starter and up; below Starter (Intro and the free sign-up lookups) the key is present with null.

netblock_org
string | null
required

The organization the registry lists as holding that block. Starter and up; below Starter (Intro and the free sign-up lookups) the key is present with null.

cdn_operator
string | null
required

The CDN operator. Set only when the classification is cdn, and null otherwise.

metadata
object
required

Extra detection detail. An empty object when the IP has no classification, or when the label is inferred from the ASN alone with no listed range behind it (network is then null too).

reasons
object[]
required

Reason codes that explain the classification, each with a detail object. The codes are stable. Empty when there is nothing to explain, for example when the classification is unknown. Codes that rest on network-telemetry signals are not returned on any plan today.

asn_abuse
object | null
required

Abuse profile of the ASN that announces the IP. Null when we hold no score for that ASN, or when the check could not run (see data_status). Every plan gets abuse_score and abuse_level. Pro and up also get flagged_ratio, flagged_ip_count and total_announced_ips, which are not returned on lower plans.

sanctions_risk
object | null
required

Reserved for a sanctions-exposure assessment. Null on every plan; its fields are not part of this version of the API.

operator_profile
object | null
required

Facts we hold about the proxy network named in provider. Null when provider is null, names more than one network, or we hold no profile for it, which includes VPN services. Pro and up; below Pro the key is present with null.

operator_group
string | null
required

The corporate group behind the named provider. Null when provider is null, or when we know no group for it. Starter and up, and Pro and up when the classification is a residential proxy label, the same rule as provider; below that plan the key is present with null.

The legal name of the company behind that group. Null when provider is null, or when we know no legal name for it. Starter and up, and Pro and up when the classification is a residential proxy label, the same rule as provider; below that plan the key is present with null.

original_classification
string

The classification before any ASN-abuse promotion. It equals classification unless asn_abuse_promoted is true. Starter and up; not returned on Intro or the free sign-up lookups.

asn_abuse_promoted
boolean

True when a hosting address was relabelled proxy because of its ASN's abuse profile. Starter and up; not returned on Intro or the free sign-up lookups.

hosting_risk_calibrated
boolean

True when risk_score for a hosting address was set from its ASN's abuse profile. False otherwise. Starter and up; not returned on Intro or the free sign-up lookups.

data_status
object

Not always present: returned only when a check could not run. Each key it holds is set to degraded, and the matching field (asn_abuse or sanctions_risk) is then null because the check failed, not because no risk was found.

observed_location
object | null

Enterprise only: the key is not returned on other plans. Null when we hold no observation for the IP.

vpn_exit_confidence
number

Reserved. Not returned on any plan today. It is a Pro and up score, from 0.5 to 0.99, of how strongly our other signals back the VPN brand attribution when the classification is vpn and the source is dns_enumeration; it does not say whether the exit is in use right now.

Required range: 0.5 <= x <= 0.99