Know when a patient's location is masked
A clinician may only treat patients where they're licensed, and a VPN hides where the patient is. Look up the address at intake, and confirm the location with the patient when it's masked.
- ISPHome broadbandVisit startsVisit, patient P-2041198.51.100.18
- VPNNordVPNConfirm locationVisit, patient P-2042203.0.113.70
- Residential ProxyExtra verificationPortal log-in192.0.2.88
- HostingLinodeBlockedBooking192.0.2.150
What it stops
Out-of-area visits
A patient on a VPN who appears to be somewhere your clinicians are licensed.
Caught byis_vpnis_relayPortal takeover
Stolen patient log-ins tried from proxy pools.
Caught byis_resproxyis_torPharmacy orders
Prescriptions ordered through a VPN from places you can't ship or prescribe to.
Caught byis_vpnlocation.countryBooking bots
Appointment slots grabbed by scripts on hosting servers.
Caught byis_hostingis_dcproxy
The fields that decide it
The four a rule here reads most, each marked with the plan that answers it.
is_vpnA commercial VPN, whose location isn't the patient's.Unlimitedis_relayA privacy relay such as iCloud Private Relay, which keeps only an approximate location.Unlimitedlocation.countryThe address's country. For a state, ask the patient.Unlimitedis_resproxyA home connection resold as a proxy, used to try stolen log-ins.Paid plans
Where to check
- 01
At intake
Look up the address before the visit starts. When it's a VPN or a relay, ask the patient to confirm where they are, since the clinician's license depends on it.
- 02
At log-in
Check log-ins to the patient portal. One from a residential proxy or Tor gets a second factor, since stolen patient log-ins are tried through proxy pools.
- 03
At pharmacy checkout
Look up the address before a prescription ships. An order through a VPN from outside the places you ship or prescribe to goes to a pharmacist first.
Start free, then add every field
The same rule runs with no key and with one. Without a key the paid fields are left out of the answer, so the second check waits for your upgrade.
- 1
Call it with no key
UnlimitedThe snippet runs as it is: the VPN, Tor and relay flags, the location and the network, with no daily or monthly cap.
- 2
Sign up for a key
No cardYour account's first 100 lookups each day answer every field, so you can try the paid half of the rule on real traffic.
- 3
Upgrade for every lookup
From $19 a monthEvery paid plan answers every field on every lookup, proxies, hosting and the operator behind each flag, and up to 1,000 addresses a batch.
import { VPNDetection } from "vpndetection";// No key needed. With one, every field answers.const client = new VPNDetection({ apiKey: process.env.VPNDETECTION_API_KEY });export async function beforeVisit(visit) {const r = await client.lookup(visit.ip);if (r.isVpn || r.isRelay || r.isTor) {return confirmLocation(visit);}// Proxies and hosting answer on a paid plan.if (r.isResproxy) {return requireSecondFactor(visit);}}
Common questions
Does it tell us which state a patient is in?
No. Our location is the country. It tells you when an address hides where the patient is, so you know to ask.
Do lookups include patient data?
No. A lookup sends only an IP address, nothing about the patient. Each request is kept for 13 months for billing questions, support and abuse investigation.
Will patients on iCloud Private Relay be flagged as VPNs?
No. Private Relay comes back as is_relay, apart from is_vpn. It keeps only an approximate location, so confirm the state with the patient.
Can we run lookups inside our own network?
Yes. The databases are licensed per dataset, bundled with Enterprise plans, and download daily as CSVGZ, and MMDB where one is built, so no address leaves your servers.
What does it cost?
The VPN and relay flags are free with no cap. Every paid plan answers every field, from Starter at $19 a month for 250,000 lookups to Max at $199 for 5,000,000, and Enterprise is priced to your volume.
Unlimited lookups, no sign-up.
Paste it into a terminal. Any address answers its VPN, Tor and relay flags, where it is and which network announces it, with no daily or monthly cap.
{"ip": "146.70.116.130","is_vpn": true,"is_relay": false,"is_tor": false,"location": {"country": "AT", ...},"asn": { "asn": 9009, ... }}