Blocking VPN traffic used to be a cheap way to cut fraud. It is now a cheap way to lose customers. Security-conscious people, remote workers on a corporate tunnel, travellers on hotel networks, and every iPhone owner who turned on iCloud Private Relay arrive through an anonymising network, and most of them are exactly who you want. The question is no longer "is this a VPN" but "which one, and what should that change". This guide lays out a policy that answers it with the fields in one lookup.
Three anonymisers, three different people
The response separates the networks that hide an address into three flags, because they carry three different meanings.
is_tor is a listed Tor exit, from the Tor Project's own bulk exit list (https://check.torproject.org/torbulkexitlist, checked 2026-09-04). Tor is a general-purpose anonymity network with a real population of journalists, researchers and people in censored countries, and a real population of abuse. It carries the highest weight, 70, because the operator of an exit has no relationship with the person behind it and no way to hold them accountable.
is_vpn is a known commercial VPN exit. Three providers publish their server lists and are matched by name, Mullvad, NordVPN and Private Internet Access, with privacy_service naming the one that matched; the open X4BNet list covers the rest without a name. A VPN customer has an account, often a paid one, with a provider that can be served legal process. That is a very different person from a Tor exit, which is why the weight is 30.
is_relay is an iCloud Private Relay egress address, from the list Apple publishes at https://mask-api.icloud.com/egress-ip-ranges.csv, complete with the city Apple assigns to each range. Private Relay is on by default for iCloud+ subscribers in Safari and hides the user's address from websites while still placing them in roughly the right region (Apple's description: https://support.apple.com/en-us/102602, checked 2026-09-04). A relay user is an ordinary Apple customer who did nothing but pay for storage. The weight is 10, and it comes with two rules that keep it honest.
The two relay rules
Relay egress runs on CDN infrastructure, so the same addresses sit inside datacenter ranges. Without a rule, every relay user would score 40 for datacenter plus 10 for relay and land in the medium band as a suspected bot. So the datacenter weight is skipped when is_relay is true. The is_datacenter flag itself still reports true, because the address really is on hosting infrastructure; only the arithmetic changes, and risk_signals shows it:
"is_datacenter": true,
"hosting_provider": null,
"is_vpn": false,
"is_relay": true,
"privacy_service": "iCloud Private Relay",
"is_anonymous": true,
"risk_score": 10,
"risk_level": "low",
"risk_signals": [
{ "signal": "datacenter", "weight": 0, "dataset": "datacenter-ranges" },
{ "signal": "relay", "weight": 10, "dataset": "relay-ranges" }
]
The second rule concerns the aggregate VPN list, which classifies Apple's relay ranges as VPN space. Apple's own list is the first-party source, so on relay egress is_vpn answers false unless a VPN provider's own list names the address. A relay user is therefore never counted as a VPN user by accident.
A policy in four tiers
Write the policy against the flags, and use is_anonymous, which is true when any of the three is, only as the coarse switch for "apply the anonymiser tier at all".
- Nothing anonymised,
is_anonymous: false. No friction. This is the large majority of traffic. - Relay,
is_relay: true. No friction either. Treat the location as regional rather than exact, since Apple assigns the city, and never rate-limit by address: many relay users share each egress address, so one hot address is a crowd, not an attacker. - Named VPN,
is_vpn: truewith aprivacy_service. Allow the action, and step up only where the action is sensitive: a payment from a new device, a password change, a withdrawal. Use a challenge you already have, such as an email confirmation or a one-time code, rather than a refusal. A paying customer on Mullvad should never see "VPN detected, access denied". - Tor,
is_tor: true. Decide per product. A publisher may want Tor readers; a marketplace may require a verified email before listing anything; a bank may refuse. Whatever the answer, make it a deliberate rule for Tor alone, not a side effect of a VPN block.
Unnamed VPN ranges, is_vpn: true with privacy_service: null, come from the aggregate list, which classifies whole networks. Treat them like a named VPN for stepping up, but expect more false positives, and let a confirmed email or a completed payment clear the address for that account.
Challenge, do not block
Every step-up above shares a property: a person can pass it and a script usually cannot. That is the whole design. A block tells a legitimate visitor nothing they can act on and tells an attacker exactly which network to switch to. A challenge lets the person through at the cost of a minute and leaves the attacker holding a burner mailbox.
Pick the challenge by what the action puts at risk, not by the flag:
| Action | Anonymised visitor | What to ask for |
|---|---|---|
| Reading, browsing, pricing | any | nothing |
| Free signup | relay | nothing |
| Free signup | VPN or Tor | a confirmed email before the trial starts |
| First payment | VPN | the card check you already run |
| First payment | Tor | your policy for Tor, applied consistently |
| Withdrawal or payout | any anonymiser | a second factor |
Record the flags with the decision, so a support agent looking at a complaint can see that the account was challenged because is_tor was true on a payout, not because a score crossed a line nobody can explain. risk_signals is built for exactly that log line.
What the flags cannot see
Residential proxies rent out addresses on home connections. They look like a person on a home line in every field of the response: asn_type: "isp", is_datacenter: false, no anonymiser flag. No open dataset can tell them apart, and this API does not claim to. If your abuse is coming through residential proxies, the network flags will be clean and the evidence will be behavioural: velocity, address reuse across accounts, a located country that never matches the billing country. Read the datacenter guide for the complementary check, and keep the anonymiser tier for what it can actually see.
Keep the location honest for VPN users
A VPN exit's location is the exit's, not the person's. When Mullvad or NordVPN place the exit in Tirana, the response says country: "AL" with location_source: "operator", because the provider's own server list is the authority on where its exit is. That is the right answer to "where does this visitor appear to be" and the wrong answer to "where does this visitor live". For currency, consent and time zone defaults, prefer the account's stored preferences over the lookup whenever is_anonymous is true; the consent and defaults guide covers the rest of that decision.
What to do next
- Read the IP intelligence guide for the field list, the risk arithmetic and worked examples.
- Try a Mullvad exit and an iCloud Private Relay address on the product page to see the two rules in the response.
- Pair this policy with block datacenter and bot signups with one IP lookup for the traffic that is not a person at all.
- Check the endpoint reference for the exact shape of
risk_signalsandsources.