Docs

Risk-score methodology

The GeoQ risk score is deliberately simple and fully documented. There is no machine-learning black box — you can reproduce any score by hand.

The formula

score = min(100, Σ weight(signal) for each triggered signal)

Signal weights

SignalWeightWhy
is_tor+45Tor exit node — strong anonymisation
is_proxy+40Open/anonymising proxy (residential-proxy detection in beta)
is_datacenter+35Hosting / cloud range, not a residential ISP
is_vpn+30Known commercial VPN range
is_bot+25Automation / crawler heuristics (beta)

Levels

LevelScore range
low0–29
medium30–59
high60–100

Worked examples

  • Datacenter only → 35 → medium. (reasons: ["is_datacenter"])
  • VPN + datacenter → 30 + 35 = 65 → high.
  • Tor + datacenter → 45 + 35 = 80 → high.
  • Proxy + datacenter + bot → 40 + 35 + 25 = 100 → high (capped).
  • No signals → 0 → low.

Reproduce it yourself

const WEIGHTS = { is_tor: 45, is_proxy: 40, is_datacenter: 35, is_vpn: 30, is_bot: 25 };

function scoreOf(signals) {
  const reasons = Object.keys(WEIGHTS).filter((k) => signals[k]);
  const score = Math.min(100, reasons.reduce((s, k) => s + WEIGHTS[k], 0));
  const level = score >= 60 ? "high" : score >= 30 ? "medium" : "low";
  return { score, level, reasons };
}

Why we publish this

A score you can't explain is a score you can't defend — to your users, your auditors or a regulator. By documenting the formula we let you audit every decision, tune your own thresholds, and avoid relying on GeoQ as the sole basis of an automated decision about a person. See our acceptable use policy and the accuracy benchmark.