The most common pattern: classify one IP at a time.
import httpx, osresp = httpx.get( "https://vpn-proxy-detection.whoisxmlapi.com/api/v1", params={"apiKey": os.environ["WXA_API_KEY"], "ipAddress": ip},)data = resp.json()if (data["is_vpn"] and not data["is_corporate_vpn"]) or data["is_proxy"] or data["is_residential_proxy"] or data["is_tor"]: block_signup(data)
is_vpn, is_proxy, is_residential_proxy, is_tor, is_hosting,
is_cdn, is_relay are the boolean flags. is_vpn is also true for a company
VPN appliance, which sets is_corporate_vpn; the sample lets those users
through. Test any rule on your own traffic before you enforce it.
Suspected VPN labels never set the booleans.classification can return
the corroboration-only labels suspected_vpn and its legacy spelling
vpn_suspect (same meaning, written by an older ingestion path) for IPs where
traffic patterns resemble VPN behavior but we lack confirmed protocol
evidence. By design they return is_vpn: false and set no other boolean.
suspected_proxy is different: it sets is_proxy: true, so a rule on
is_proxy blocks it. If your integration reads only the top-level
classification, treat suspected_vpn / vpn_suspect as advisory: gate on
the booleans (or on by_primary_category semantics) for block/allow
decisions, and on Pro and up use confidence to tune how much weight a
suspect label gets (it is null on Intro and Starter). For reference, is_vpn: true corresponds exactly to
classification in vpn, commercial_vpn, corporate_vpn,
vpn_concentrator (retired 2026-10; no longer assigned), or vpn_hosting —
confirmed VPN endpoints only;
tor and relay have their own dedicated booleans.
On every plan, a residential proxy hit’s risk_score follows 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 bucket never lowers it.On a mobile carrier, a satellite network or a secure web gateway, many people
share one address, so a proxy sighting there says little about the person in
front of you. A residential proxy hit on one of these networks that we list
scores at most 60, however recent, and carries the SHARED_ADDRESS_NETWORK
reason, with the kind of network in detail.network_type. The list does not
yet cover every such network, so the reason, not the network’s type, tells
you the cap applied. Step those hits up, with a challenge
or a review, rather than block them: the sample above blocks every residential
proxy hit, so a rule that blocks only above 60 and steps up the rest follows
this advice.
Up to 100 IPs per request. results holds one row per distinct IP string, in
the order each first appears. An exact repeat is looked up once, so send each
IP in canonical form and match rows to your inputs by ip, not by position. A
row is either a lookup result with the same fields as the single-IP endpoint,
or {"ip": ..., "error": ...} for an IP that could not be looked up; see the
batch endpoint reference.
If you’re checking >1 M IPs/day, don’t use the API one-at-a-time —
use the bulk export for nightly mirroring and
hit local storage.If you need per-IP lookups at that scale, use the MMDB download:
local lookups with no rate limits. The files regenerate once
a day, so pull them daily via cron. The API itself refreshes daily too, so a
daily mirror stays within about a day of what the API returns.
If you think a lookup got an address wrong, email
service.desk@whoisxmlapi.com.
The link starts the email for you. These help us look into it:
The IP address.
When you looked it up, in UTC.
What we returned: paste the response, or at least classification, the
is_* flags and risk_score.
What you expected, and why: for example, that the address is your own
office’s.
Leave your API key out of the email.
{"docsConfig":{"$schema":"https://mintlify.com/docs.json","theme":"mint","name":"VPN \u0026 Proxy Detection API","colors":{"primary":"#0F62FE","light":"#4589FF","dark":"#002D9C"},"favicon":"https://mintlify.s3.us-west-1.amazonaws.com/whoisapi/images/favicon.png","logo":{"light":"https://mintlify.s3.us-west-1.amazonaws.com/whoisapi/images/logo.svg","dark":"https://mintlify.s3.us-west-1.amazonaws.com/whoisapi/images/logo-dark.svg"},"api":{"openapi":["openapi.json"]},"navbar":{"links":[{"label":"Support","href":"mailto:service.desk@whoisxmlapi.com"}],"primary":{"type":"button","label":"Sign Up","href":"https://vpn-proxy-detection.whoisxmlapi.com/api/signup"}},"search":{"prompt":"Ask anything about VPN, proxy, or IP intelligence APIs..."},"footer":{"socials":{"website":"https://www.whoisxmlapi.com","github":"https://github.com/whois-api-llc"}},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"Pricing","href":"https://vpn-proxy-detection.whoisxmlapi.com/api/pricing","icon":"tag"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"whoisapi","hasAudioNarration":false,"actualSubdomain":"whoisapi","customDomains":["vpn-docs.wxapros.com"],"gitSource":{"type":"github","owner":"whois-api-llc","repo":"wxa_vpn","deployBranch":"main","contentDirectory":"docs/api-reference","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae984eac5625f8486aa58b7","collectionId":"1900f435-482d-49ba-b279-086d15facb13","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae984eac5625f8486aa58b7"},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ae984ef93c14f424a7bb1c5","clientVersion":"0.0.4045","searchFilterCounts":[{"language":"default","tag":"Documentation","count":25},{"language":"default","tag":"Guides","count":6},{"language":"default","tag":"Aggregates","count":5},{"language":"default","tag":"Bulk Exports","count":4},{"language":"default","tag":"Getting Started","count":4},{"language":"default","tag":"Lookup","count":3},{"language":"default","tag":"Reference","count":2},{"language":"default","tag":"Account","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"guides/lookups","slug":"/guides/lookups","pageMetadata":{"title":"IP Lookups","description":"Single, batch, and high-volume lookup patterns.","href":"/guides/lookups"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Single, batch, and high-volume lookup patterns.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,em:`em`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`2`,id:`single-ip`,children:`Single IP`}),`\n`,_jsx(_components.p,{children:`The most common pattern: classify one IP at a time.`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`8`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`8`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` httpx, os`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`resp `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` httpx.get(`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"https://vpn-proxy-detection.whoisxmlapi.com/api/v1\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:` params`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"apiKey\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: os.environ[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"WXA_API_KEY\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`], `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"ipAddress\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: ip},`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`data `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` resp.json()`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (data[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"is_vpn\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`and`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` not`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` data[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"is_corporate_vpn\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`or`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` data[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"is_proxy\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`or`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` data[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"is_residential_proxy\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`or`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` data[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"is_tor\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]:`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` block_signup(data)`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`is_vpn`}),`, `,_jsx(_components.code,{children:`is_proxy`}),`, `,_jsx(_components.code,{children:`is_residential_proxy`}),`, `,_jsx(_components.code,{children:`is_tor`}),`, `,_jsx(_components.code,{children:`is_hosting`}),`,\n`,_jsx(_components.code,{children:`is_cdn`}),`, `,_jsx(_components.code,{children:`is_relay`}),` are the boolean flags. `,_jsx(_components.code,{children:`is_vpn`}),` is also true for a company\nVPN appliance, which sets `,_jsx(_components.code,{children:`is_corporate_vpn`}),`; the sample lets those users\nthrough. Test any rule on your own traffic before you enforce it.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Suspected VPN labels never set the booleans.`}),` `,_jsx(_components.code,{children:`classification`}),` can return\nthe corroboration-only labels `,_jsx(_components.code,{children:`suspected_vpn`}),` and its legacy spelling\n`,_jsx(_components.code,{children:`vpn_suspect`}),` (same meaning, written by an older ingestion path) for IPs where\ntraffic patterns `,_jsx(_components.em,{children:`resemble`}),` VPN behavior but we lack confirmed protocol\nevidence. By design they return `,_jsx(_components.code,{children:`is_vpn: false`}),` and set no other boolean.\n`,_jsx(_components.code,{children:`suspected_proxy`}),` is different: it sets `,_jsx(_components.code,{children:`is_proxy: true`}),`, so a rule on\n`,_jsx(_components.code,{children:`is_proxy`}),` blocks it. If your integration reads only the top-level\n`,_jsx(_components.code,{children:`classification`}),`, treat `,_jsx(_components.code,{children:`suspected_vpn`}),` / `,_jsx(_components.code,{children:`vpn_suspect`}),` as `,_jsx(_components.em,{children:`advisory`}),`: gate on\nthe booleans (or on `,_jsx(_components.code,{children:`by_primary_category`}),` semantics) for block/allow\ndecisions, and on Pro and up use `,_jsx(_components.code,{children:`confidence`}),` to tune how much weight a\nsuspect label gets (it is `,_jsx(_components.code,{children:`null`}),` on Intro and Starter). For reference, `,_jsx(_components.code,{children:`is_vpn: true`}),` corresponds exactly to\n`,_jsx(_components.code,{children:`classification`}),` in `,_jsx(_components.code,{children:`vpn`}),`, `,_jsx(_components.code,{children:`commercial_vpn`}),`, `,_jsx(_components.code,{children:`corporate_vpn`}),`,\n`,_jsx(_components.code,{children:`vpn_concentrator`}),` (retired 2026-10; no longer assigned), or `,_jsx(_components.code,{children:`vpn_hosting`}),` —\nconfirmed VPN endpoints only;\n`,_jsx(_components.code,{children:`tor`}),` and `,_jsx(_components.code,{children:`relay`}),` have their own dedicated booleans.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`residential-proxy-hits`,children:`Residential proxy hits`}),`\n`,_jsxs(_components.p,{children:[`On every plan, a residential proxy hit’s `,_jsx(_components.code,{children:`risk_score`}),` follows how recently we\nsaw the address, in the `,_jsx(_components.code,{children:`freshness_class`}),` buckets (the bucket itself is shown\nfrom Pro): current 95–100, recent 75–85, stale 45–60, frozen 25–35. Within a\nbucket, an address seen on more days and through more networks scores higher.\nA VPN, proxy, threat-list or hosting match on the same address keeps the score\nit would have on its own, so the bucket never lowers it.`]}),`\n`,_jsxs(_components.p,{children:[`On a mobile carrier, a satellite network or a secure web gateway, many people\nshare one address, so a proxy sighting there says little about the person in\nfront of you. A residential proxy hit on one of these networks that we list\nscores at most 60, however recent, and carries the `,_jsx(_components.code,{children:`SHARED_ADDRESS_NETWORK`}),`\nreason, with the kind of network in `,_jsx(_components.code,{children:`detail.network_type`}),`. The list does not\nyet cover every such network, so the reason, not the network’s type, tells\nyou the cap applied. Step those hits up, with a challenge\nor a review, rather than block them: the sample above blocks every residential\nproxy hit, so a rule that blocks only above 60 and steps up the rest follows\nthis advice.`]}),`\n`,_jsx(Heading,{level:`2`,id:`batch`,children:`Batch`}),`\n`,_jsx(_components.p,{children:`For lists of IPs (Starter tier and above), batch endpoint cuts latency\ndramatically:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`8`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`8`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`resp `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` httpx.post(`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"https://vpn-proxy-detection.whoisxmlapi.com/api/v1/ip/batch\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:` params`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"apiKey\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: key},`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:` headers`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Content-Type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"application/json\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`},`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:` json`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"ips\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"1.1.1.1\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"8.8.8.8\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"62.182.99.141\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]},`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:` timeout`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`30`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`results `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` resp.json()[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"results\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Up to 100 IPs per request. `,_jsx(_components.code,{children:`results`}),` holds one row per distinct IP string, in\nthe order each first appears. An exact repeat is looked up once, so send each\nIP in canonical form and match rows to your inputs by `,_jsx(_components.code,{children:`ip`}),`, not by position. A\nrow is either a lookup result with the same fields as the single-IP endpoint,\nor `,_jsx(_components.code,{children:`{\"ip\": ..., \"error\": ...}`}),` for an IP that could not be looked up; see the\n`,_jsx(_components.a,{href:`/api-reference/lookup-batch`,children:`batch endpoint reference`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`high-volume`,children:`High-volume`}),`\n`,_jsxs(_components.p,{children:[`If you’re checking >1 M IPs/day, `,_jsx(_components.strong,{children:`don’t`}),` use the API one-at-a-time —\nuse the `,_jsx(_components.a,{href:`/guides/bulk-export`,children:`bulk export`}),` for nightly mirroring and\nhit local storage.`]}),`\n`,_jsxs(_components.p,{children:[`If you need per-IP lookups at that scale, use the `,_jsx(_components.a,{href:`/api-reference/export-mmdb`,children:`MMDB download`}),`:\nlocal lookups with no rate limits. The files regenerate once\na day, so pull them daily via cron. The API itself refreshes daily too, so a\ndaily mirror stays within about a day of what the API returns.`]}),`\n`,_jsxs(Heading,{level:`2`,id:`what-to-do-with-unknown`,children:[`What to do with `,_jsx(_components.code,{children:`unknown`})]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`classification: \"unknown\"`}),` means we hold no label for this IP. Don’t treat unknown as either clean or suspicious — treat it as\n“no data.” Common in:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Brand new ranges (recently allocated by a RIR)`}),`\n`,_jsx(_components.li,{children:`Sparse cellular ranges with infrequent observations`}),`\n`,_jsx(_components.li,{children:`Ranges deliberately excluded from our scanning (per opt-out requests)`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Most production callers fall through `,_jsx(_components.code,{children:`unknown`}),` to their next signal\n(behavioral, device, payment risk).`]}),`\n`,_jsx(Heading,{level:`2`,id:`report-a-result-you-think-is-wrong`,children:`Report a result you think is wrong`}),`\n`,_jsxs(_components.p,{children:[`If you think a lookup got an address wrong, email\n`,_jsx(_components.a,{href:`mailto:service.desk@whoisxmlapi.com?subject=Report%20a%20result%20you%20think%20is%20wrong\u0026body=IP%20address%3A%0D%0ATime%20of%20the%20lookup%20%28UTC%29%3A%0D%0AOur%20result%20%28the%20response%2C%20or%20classification%2C%20the%20is_%2A%20flags%20and%20risk_score%29%3A%0D%0AWhat%20you%20expected%2C%20and%20why%3A%0D%0A`,children:`service.desk@whoisxmlapi.com`}),`.\nThe link starts the email for you. These help us look into it:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.strong,{children:`The IP address.`})}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`When you looked it up`}),`, in UTC.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`What we returned`}),`: paste the response, or at least `,_jsx(_components.code,{children:`classification`}),`, the\n`,_jsx(_components.code,{children:`is_*`}),` flags and `,_jsx(_components.code,{children:`risk_score`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`What you expected, and why`}),`: for example, that the address is your own\noffice’s.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`Leave your API key out of the email.`})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"IP Lookups","description":"Single, batch, and high-volume lookup patterns.","href":"/guides/lookups"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Single IP","slug":"single-ip","depth":2,"children":[]},{"title":"Residential proxy hits","slug":"residential-proxy-hits","depth":2,"children":[]},{"title":"Batch","slug":"batch","depth":2,"children":[]},{"title":"High-volume","slug":"high-volume","depth":2,"children":[]},{"title":"What to do with unknown","slug":"what-to-do-with-unknown","depth":2,"children":[]},{"title":"Report a result you think is wrong","slug":"report-a-result-you-think-is-wrong","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"whoisapi","siteName":"VPN \u0026 Proxy Detection API","title":"IP Lookups - VPN \u0026 Proxy Detection API","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-03T06:53:47.360Z","originalFileLocation":"guides/lookups.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Single, batch, and high-volume lookup patterns.\">\u003cmeta data-mint-head name=\"application-name\" content=\"VPN \u0026amp; Proxy Detection API\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/whoisapi/images/favicon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/whoisapi/images/favicon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/whoisapi/images/favicon.png\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/png\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/whoisapi/images/favicon.png\">\u003cmeta data-mint-head property=\"og:title\" content=\"IP Lookups - VPN \u0026amp; Proxy Detection API\">\u003cmeta data-mint-head property=\"og:description\" content=\"Single, batch, and high-volume lookup patterns.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"VPN \u0026amp; Proxy Detection API\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://vpn-docs.wxapros.com/guides/lookups\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://whoisapi.mintlify.app/_mintlify/api/og/v2?division=Guides\u0026amp;title=IP+Lookups\u0026amp;description=Single%2C+batch%2C+and+high-volume+lookup+patterns.\u0026amp;theme=2d814d5bab6035f0e6472a06\u0026amp;signature=da2cde69dfede9690ea43f6facee91820d423f8e0df4c3db55875ed84d0b84b7\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"IP Lookups - VPN \u0026amp; Proxy Detection API\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Single, batch, and high-volume lookup patterns.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://whoisapi.mintlify.app/_mintlify/api/og/v2?division=Guides\u0026amp;title=IP+Lookups\u0026amp;description=Single%2C+batch%2C+and+high-volume+lookup+patterns.\u0026amp;theme=2d814d5bab6035f0e6472a06\u0026amp;signature=da2cde69dfede9690ea43f6facee91820d423f8e0df4c3db55875ed84d0b84b7\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"https://mintlify.s3.us-west-1.amazonaws.com/whoisapi/_generated/favicon/browserconfig.xml?v=3\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"VPN \u0026amp; Proxy Detection API\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0F62FE\">\u003clink data-mint-head rel=\"canonical\" href=\"https://vpn-docs.wxapros.com/guides/lookups\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/guides/lookups.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://vpn-docs.wxapros.com/#organization\",\"name\":\"VPN \u0026 Proxy Detection API\",\"url\":\"https://vpn-docs.wxapros.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintlify.s3.us-west-1.amazonaws.com/whoisapi/images/logo.svg\"}},{\"@type\":\"WebSite\",\"@id\":\"https://vpn-docs.wxapros.com#website\",\"name\":\"VPN \u0026 Proxy Detection API\",\"url\":\"https://vpn-docs.wxapros.com\",\"publisher\":{\"@id\":\"https://vpn-docs.wxapros.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://vpn-docs.wxapros.com/guides/lookups#webpage\",\"url\":\"https://vpn-docs.wxapros.com/guides/lookups\",\"name\":\"IP Lookups\",\"description\":\"Single, batch, and high-volume lookup patterns.\",\"dateModified\":\"2026-11-03T06:53:47.360Z\",\"isPartOf\":{\"@id\":\"https://vpn-docs.wxapros.com#website\"},\"breadcrumb\":{\"@id\":\"https://vpn-docs.wxapros.com/guides/lookups#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://vpn-docs.wxapros.com/guides/lookups#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"VPN \u0026 Proxy Detection API\",\"item\":\"https://vpn-docs.wxapros.com\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"IP Lookups\",\"item\":\"https://vpn-docs.wxapros.com/guides/lookups\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://vpn-docs.wxapros.com/guides/lookups#article\",\"headline\":\"IP Lookups\",\"name\":\"IP Lookups\",\"description\":\"Single, batch, and high-volume lookup patterns.\",\"url\":\"https://vpn-docs.wxapros.com/guides/lookups\",\"mainEntityOfPage\":{\"@id\":\"https://vpn-docs.wxapros.com/guides/lookups#webpage\"},\"dateModified\":\"2026-11-03T06:53:47.360Z\",\"publisher\":{\"@id\":\"https://vpn-docs.wxapros.com/#organization\"},\"isPartOf\":{\"@id\":\"https://vpn-docs.wxapros.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"VPN \u0026 Proxy Detection API\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"VPN \u0026 Proxy Detection API","nav":{"global":{"anchors":[{"anchor":"Pricing","href":"https://vpn-proxy-detection.whoisxmlapi.com/api/pricing","icon":"tag"}]},"anchors":[{"anchor":"Documentation","icon":"book-open","groups":[{"group":"Getting Started","pages":[{"title":"Introduction","href":"/introduction"},{"title":"Quickstart","href":"/quickstart"},{"title":"Authentication","href":"/authentication"},{"title":"Tiers","description":"What each tier unlocks — quotas, rate limits, fields, and bulk data.","href":"/tiers"}]},{"group":"Guides","pages":[{"title":"IP Lookups","href":"/guides/lookups"},{"title":"Categories and actions","description":"What each classification tells you, and a default action to start from at a decision point.","href":"/guides/categories-and-actions"},{"title":"Point-in-time lookups","href":"/guides/point-in-time"},{"title":"Bulk Exports","href":"/guides/bulk-export"},{"title":"ASN Abuse","href":"/guides/asn-abuse"},{"title":"Error Handling","href":"/guides/error-handling"}]},{"group":"Reference","pages":[{"title":"API Reference Overview","href":"/api-reference/overview"},{"title":"Changelog","href":"/changelog"}]},{"group":"Lookup","pages":[{"title":"Look up a single IP","openapi":"GET /api/v1","href":"/api-reference/lookup-ip"},{"title":"Batch IP lookup","openapi":"POST /api/v1/ip/batch","href":"/api-reference/lookup-batch"},{"title":"Shadow VPN lookup","openapi":"GET /api/v1/shadow_vpn/lookup/{ip}","href":"/api-reference/shadow-vpn-lookup"}]},{"group":"Aggregates","pages":[{"title":"Global stats","openapi":"GET /api/v1/stats","href":"/api-reference/stats"},{"title":"List providers","openapi":"GET /api/v1/providers","href":"/api-reference/providers"},{"title":"Per-country VPN stats","openapi":"GET /api/v1/stats/country/{code}","href":"/api-reference/country-stats"},{"title":"ASN abuse leaderboard","openapi":"GET /api/v1/stats/asn-abuse","href":"/api-reference/asn-abuse-stats"},{"title":"ASN reputation","openapi":"GET /api/v1/asn/{asn}","href":"/api-reference/asn-reputation"}]},{"group":"Bulk Exports","pages":[{"title":"Export CSV","openapi":"GET /api/v1/export/csv","href":"/api-reference/export-csv"},{"title":"Export MMDB","openapi":"GET /api/v1/export/mmdb","href":"/api-reference/export-mmdb"},{"title":"Export Parquet","openapi":"GET /api/v1/export/parquet","href":"/api-reference/export-parquet"},{"title":"Export dataset listing","openapi":"GET /api/v1/export/dataset","href":"/api-reference/export-dataset"}]},{"group":"Account","pages":[{"title":"Coverage report","openapi":"GET /api/v1/coverage/report","href":"/api-reference/coverage-report"}]}]}]},"basePath":"","title":"IP Lookups - VPN \u0026 Proxy Detection API","buildId":"dpl_36EDyZCDfRuoUD9af5CH4M1bqY2h","deploymentId":"dpl_36EDyZCDfRuoUD9af5CH4M1bqY2h","dynamics":[],"chunks":[]}