VPN Detection API: Security Flags from an IP
A VPN detection API is a REST endpoint that returns boolean security flags for an IPv4/IPv6 address. On ipXapi those flags live on GET /api/ip?ip= inside the security object: is_vpn, is_proxy, is_tor, plus cloud, bogon, and threat bits. Auth is Authorization: Bearer YOUR_KEY.
The official response example on the test-drive docs uses 148.105.12.120 (MailChimp / AS14782, Mountain View, CA). In that fixture is_vpn is false and is_cloud_provider is true — do not treat cloud as VPN. Basic is $29.99/mo. Trial is 7 days or 50 requests, whichever comes first. Playground: ipxapi.com.
Request: security flags for 148.105.12.120
curl "https://ipxapi.com/api/ip?ip=148.105.12.120" \
-H "Accept: application/json" \
-H "Authorization: Bearer YOUR_KEY"
The ip query param is required. The same host also exposes /api/abuse-check, /api/blacklist-check, and /api/fraud-score (docs examples use 8.8.8.8). This post does not reprint those bodies — copy them from the product docs. Batch lookups return a results array of the same object shape as /api/ip.
Response: security object (MailChimp fixture)
Official example from the ipXapi test-drive docs (148.105.12.120). Location fields are in the same envelope; the gate for VPN/proxy/Tor is security:
{
"status": "success",
"country": "United States",
"countryCode": "US",
"region": "US-CA",
"regionName": "California",
"city": "Mountain View",
"zip": "94043",
"lat": 37.40599,
"lon": -122.0786,
"timezone": "America/Los_Angeles",
"isp": "MailChimp",
"org": "MailChimp",
"as": "AS14782 MailChimp",
"query": "148.105.12.120",
"inEU": false,
"continentCode": "NA",
"continentName": "North America",
"currencyCode": "USD",
"currencySymbol": "$",
"currencySymbol_UTF8": "$",
"flag": "🇺🇸",
"callingCode": "1",
"languageCode": "en",
"security": {
"is_proxy": false,
"is_tor": false,
"is_tor_exit": false,
"is_abuser": false,
"is_attacker": false,
"is_bogon": false,
"is_cloud_provider": true,
"is_relay": false,
"is_vpn": false,
"is_anonymous": false,
"is_threat": false
}
}
query echoes the IP you sent. In this sample security.is_cloud_provider is true (MailChimp) while is_vpn, is_proxy, and is_tor are false. A datacenter or ESP address is not a VPN exit.
When to treat is_vpn as a hard block
- Sign-up / one-time promo. If you limit one trial per household,
security.is_vpnplusis_proxy/is_toris the cheap filter. Do not blockis_cloud_provideralone — CI runners and MailChimp-class hosts are cloud, not VPN. - Account takeover. Flag a session when the login IP’s
is_vpnflips relative to the last trusted city. Pair withasso a new ASN is visible in the ticket. - Geo-restricted media. VPN true often means “treat as unknown country” rather than trusting
countryCodefor licensing.
Go live with security flags
1. Register and start the 7-day / 50-request trial. Basic is $29.99/mo after.
2. Copy the Bearer key from the homepage playground after login.
3. Call https://ipxapi.com/api/ip?ip=148.105.12.120 with Authorization: Bearer YOUR_KEY.
4. Gate on security.is_vpn, is_proxy, and is_tor — not on is_cloud_provider alone.
FAQ: VPN detection API
Which fields mean “this IP is a VPN”?
security.is_vpn. Pair it with is_proxy and is_tor / is_tor_exit if you also block those paths. is_cloud_provider is a separate bit.
Is the MailChimp sample a VPN?
No. The documented object has is_vpn: false and is_cloud_provider: true. Use it to test parsing, not as a positive VPN fixture.
How do I authenticate?
Authorization: Bearer YOUR_KEY. Query-string API keys are not the documented path for /api/ip.
What about abuse / blacklist / fraud-score?
Those are separate endpoints on the same host. Docs examples use 8.8.8.8. Copy the official JSON from the docs — do not assume it matches the security object above.
Get a key and check security flags →
