VPN and proxy detection: read the signals on each event
Updated
Every event carries three network signals you can read from your backend: signals.vpn.result for visits that look like they come through a VPN, signals.proxy.result for traffic that reaches you through a hosting network, and signals.ip.datacenter for visits from a hosting or cloud network instead of a home or mobile connection. They are evidence, not verdicts, and each can be null when the check could not run.
Why networks matter
A VPN or proxy hides the real address of a visitor. Plenty of honest people use a VPN at work or on public Wi-Fi, so the presence of one is a reason to look closer, not a reason to refuse.
It matters for abuse because a changing address defeats per-network limits and makes a visitor look like they are somewhere else.
The three signals
Read them from the event with your secret key. Each is true, false, or null when the check could not run.
- signals.vpn.result: the visit looks like it comes through a VPN. The signal lists the reasons.
- signals.proxy.result: the traffic reaches you through a hosting network.
- signals.ip.datacenter: the address belongs to a hosting or cloud network, not a home or mobile connection.
Read them in code
Fetch the event on your server and treat null as unknown. Do not read null as clean.
if (!/^ev_[0-9A-HJKMNP-TV-Z]{20}$/.test(eventId)) throw new Error('bad eventId'); // fail closed
const res = await fetch(`https://api.fpchecker.com/v1/events/${eventId}`, {
headers: { 'X-Secret-Key': process.env.FPCHECKER_SECRET_KEY },
});
if (!res.ok) throw new Error('event lookup failed'); // fail closed
const event = await res.json();
if (event.eventId !== eventId || !(Date.now() - Date.parse(event.createdAt) <= 5 * 60_000)) throw new Error('stale or reused event'); // wrong or old event
if (!(await markEventUsed(eventId))) throw new Error('stale or reused event'); // your store: true only the first time
const { signals } = event;
const networkFlags = [
signals?.vpn?.result === true,
signals?.proxy?.result === true,
signals?.ip?.datacenter === true,
].filter(Boolean).length;
if (networkFlags >= 2) requireHumanCheck(); // your codePick a proportionate response
A VPN alone is a weak reason to block. A hosting network, which no ordinary home user browses from, is stronger. Several network flags together with a first-time device are stronger still.
Ask for a human check on actions that cost you money and let low-risk browsing through. Rules in the console can act on vpn, proxy and ipKind, and you can test a rule against a stored event before you switch it on.
Limits
A VPN signal can be a false alarm for a traveller or a corporate network, and a determined attacker can choose a connection that looks ordinary. iCloud Private Relay on its own does not count as a VPN. Treat these signals as one input among many.
Frequently asked questions
Should I block VPN users?
Usually not. Many are honest. Ask for a human check on risky actions and combine the signal with other evidence.
What is the difference between VPN, proxy and datacenter?
VPN means the visit looks like it came through a VPN. Proxy means it reaches you through a hosting network. Datacenter says the address belongs to a hosting or cloud network.
What if a signal is null?
The check could not run, for example there was no data for that address. It is unknown, not clean.
Do these signals change the decision?
No. They are evidence for your own rules. The allow, human check or deny answer works as before.
Try FingerPrint Checker free
Every new account gets 2,000 free checks. No card required to start.
Create a free account