Skip to main content

Reasons

The Details array in the webhook payload contains every signal that fired for the session. Each entry has a Value (points added to the score) and a Description (the signal name).
"Details": [
  { "Value": 20, "Description": "Is datacenter" },
  { "Value": 30, "Description": "Stun is not checked" }
]

Complete signal list

IP Intelligence signals

DescriptionPointsMeaning
Is VPN+10IP belongs to a known VPN provider (unconfirmed)
Is vpn by base ip+15VPN confirmed by IP database
Is vpn by network & by base ip+15VPN confirmed by both network topology and IP database
Is proxy+30IP is a proxy server
Is datacenter+20IP is from a cloud or datacenter ASN
Is abuser+20IP is in abuse blacklists
Is tor+15Tor exit node

Connectivity signals

DescriptionPointsMeaning
Stun is not checked+30STUN/ICE did not complete — UDP blocked or WebRTC disabled
Browser timezone ≠ IP-timezone+10Intl timezone doesn’t match IP geolocation timezone

OS / Device signals

DescriptionPointsMeaning
UA OS is not detected+30Cannot determine OS from User-Agent
Network OS is not detected+30TCP fingerprint did not identify OS
Fail by windows os detect+30UA = Windows, TCP fingerprint = not Windows
Fail by linux os detect+30UA = Linux, TCP fingerprint = not Linux
Fail by android os detect+30UA = Android, TCP fingerprint = not Android
Fail by IOS detect+30UA = iOS, TCP fingerprint = not iOS/macOS
Fail by Mac OS detect+30UA = macOS, TCP fingerprint = not macOS/iOS

Special signals

DescriptionPointsMeaning
JavaScript disabled90Triggered by noscript beacon — JS was disabled in browser
User has been banned 1H, to many requests999Rate limit exceeded — auto-ban for 1 hour

Using signals in your logic

You can use specific signal descriptions to customize your response:
app.post('/shieldlabs/webhook', (req, res) => {
  const { Data } = req.body;
  const signals = Data.Details.map(d => d.Description);

  if (signals.includes('Is tor')) {
    // Extra friction for Tor users
    requireEmailVerification(Data.UserHID);
  }

  if (signals.some(s => s.startsWith('Fail by'))) {
    // Definite anti-detect — block
    blockUser(Data.UserHID);
  }

  res.status(200).end();
});