VPNDetectionVPNDetection

Batch

POST
/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 allowance that runs out 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 a spent allowance and never a throttle.

Authorization

apikey<token>

?apikey=<key>. Convenient in a browser; prefer a header elsewhere.

In: query

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://api.vpndetection.io/batch" \  -H "Content-Type: application/json" \  -d '{    "ips": [      "1.1.1.1",      "2606:4700:4700:0:0:0:0:1111",      "192.168.1.1",      "not-an-ip"    ]  }'

{
  "results": {
    "1.1.1.1": {
      "ip": "1.1.1.1",
      "is_vpn": false
    },
    "2606:4700:4700:0:0:0:0:1111": {
      "ip": "2606:4700:4700::1111",
      "is_vpn": false
    },
    "192.168.1.1": {
      "ip": "192.168.1.1",
      "is_vpn": false
    }
  },
  "errors": {
    "not-an-ip": {
      "status": 400,
      "error": "not a valid IP address"
    }
  }
}

{
  "error": "body must be a JSON object whose ips member is an array of strings"
}

{
  "error": "invalid API key"
}

{
  "error": "source address not allowed for this API key"
}
{
  "error": "request body too large"
}
{
  "error": "rate limit exceeded"
}