For AI agents

The whole contract, on one page.

If you are an autonomous client, this page is for you. One GET, the exact response shape, what an absent field means as against an empty one, and the two different things a 429 can mean. Nothing here needs another page to be actionable.

The same facts are at /llms.txt as plain text, and the full reference is at docs.vpndetection.io.

One call, one address

The path is the address. IPv4 and IPv6 both, on the same endpoint. The key is a bearer token; without one you still get an answer, just a narrower one.

Request
curl "https://api.vpndetection.io/45.83.91.1" \
-H "Authorization: Bearer $VPNDETECTION_API_KEY"
EndpointGET https://api.vpndetection.io/{ip}
AuthAuthorization: Bearer <key>
Content typeapplication/json, pretty-printed
Success200 with the body below
Bad address400
Key problem401
Limit or allowance429 — read Retry-After

What comes back

Eight independent flags and, for each, a detail object carrying the evidence. This is a Max plan response; a lower plan omits fields rather than nulling them.

200 application/json
{
"ip": "45.83.91.1",
"is_vpn": true,
"is_hosting": true,
"is_tor": false,
"is_relay": false,
"is_cdn": false,
"is_resproxy": false,
"is_dcproxy": false,
"is_mobproxy": false,
"vpn": {
"provider": "mullvad",
"confidence": "high",
"method": "scan",
"last_seen": "2026-09-02"
},
"hosting": { "provider": "m247", "confidence": "high", "last_seen": "2026-09-02" },
"tor": {},
"relay": {},
"cdn": {},
"resproxy": {},
"dcproxy": {},
"mobproxy": {}
}
is_vpn
A commercial VPN exit. The operator is named in the vpn object.
is_hosting
Leased hosting or cloud space. Infrastructure, not anonymity on its own.
is_tor
A Tor exit node, from the public exit set, rebuilt daily.
is_relay
A platform privacy relay, such as iCloud Private Relay.
is_cdn
A content-delivery edge. Grouped with hosting, not with anonymity.
is_resproxy
Seen in a residential proxy pool over a rolling 90-day window.
is_dcproxy
Seen in a datacenter proxy pool over the same window.
is_mobproxy
Seen in a mobile proxy pool riding carrier-assigned space.

Seven things that will bite you otherwise

Each of these is a place where the obvious reading of the response is the wrong one.

01Absent is unknown, never false

A field your plan does not include is omitted from the response. Do not read a missing key as a negative answer; read it as a question you did not buy an answer to.

02An empty object is a checked answer

A flag that is present always answers. Its detail object comes back as {} when the dataset was queried and nothing matched - that is "we looked", not "we do not know".

03Bogons never reach us and never bill

Private, loopback, link-local, documentation and multicast ranges, including their 6to4 and Teredo forms, are answered by the client without a request. Every official SDK does this; if you call the endpoint directly, do it yourself.

04Retry-After separates the two 429s

Present means a transient rate limit and retrying works. Absent means a monthly allowance is spent and retrying will not help. Branch on the header, not on the status.

05A 5xx is ours

Retry with exponential backoff and jitter. The official clients already do.

06Provider ids are stable

A provider id does not change between builds, so a rule keyed on one keeps working as that operator's ranges rotate. Join on the id, not on a display name.

07Classifications are probabilistic

They are inferences from measurement, published operator data and public registration records. They can be wrong or go stale. Do not make them the sole basis for denying a person access to a service.

What a plan lets you see

Every plan queries all eight datasets. What changes is how much of the answer is returned. Full detail is on the pricing page.

No key
ip and is_vpn, under a small daily allowance.
Free
The same fields, at 50,000 requests a month.
Starter
All eight flags, plus provider and last_seen on the VPN match.
Scale
Adds the detail object behind hosting, Tor, relay and CDN, and the three proxy flags.
Max
Every field, including confidence, method and the proxy persistence counts.

When you need more than one answer

Do not loop the API over a list you already hold. Two better paths exist.

Take the dataset

Every classification ships as a downloadable build, CSVGZ and where published MMDB, with checksums. Poll the build id and fetch only when it changes; an unchanged poll costs nothing. See the database pages.

Read the address space

Aggregates per block are public and need no key: every /8 down to /16 and /24, with how much of each block carries which signal. Individual address pages exist but are noindex and cost a live look-up, so crawl the blocks, not the addresses.

00 · No key

Start without signing up.

Paste it into a terminal — no account needed. 1k daily allowance per user, answering ip and is_vpn.

curl "https://api.vpndetection.io/45.83.91.1"
{
"ip": "45.83.91.1",
"is_vpn": true
}
01 · Free key

Signup for 50k req/month.

No card, no sales call — the key is issued on signup.
Every request flags VPN IPs.
Upgrade only when you outgrow the allowance.