Blog

Using IP signals to slow account-takeover attacks

Account takeover (ATO) is a layered problem, and IP signals are exactly one layer. They won't stop a determined attacker on their own — but used well, they raise the cost of an attack and catch the lazy majority. Let's be honest about both halves of that.

Where IP signals help

  • Anomaly detection: a login from a new country, a Tor exit, or a datacenter IP for an account that always logs in from one home ISP is worth a second factor.
  • Cheap pre-filtering: scoring the IP is one fast call before you spend money on heavier checks.
  • Velocity: a burst of high-risk logins against one account is a strong takeover signal.

Where they don't

A motivated attacker buys a residential proxy in the victim's city for pennies. IP signals will look clean. That's why IP risk is a layer, never the whole defence — and never the sole basis of a decision about a person.

A pragmatic login check

Score the IP on each login and compare to the account's normal pattern. Step up when something looks off — don't lock people out for travelling:

// On every login attempt, score the IP and compare to the account's history.
import { checkIp } from './geoq.js';

async function onLogin(req, account) {
  let r = null;
  try { r = await checkIp(req.ip); } catch { /* fail open */ }

  const newCountry = r && r.geo.country_code !== account.lastCountry;
  const risky = r && r.risk.level !== 'low';

  if (risky || newCountry) {
    await sendStepUpChallenge(account); // MFA / email code
    return 'step-up';
  }
  return 'ok';
}

Add velocity for the high-risk case

Repeated high-risk attempts against one account is the pattern you actually care about. Count them in a short window and escalate:

// Add velocity: many high-risk logins to one account => lock + notify.
if (r && r.risk.level === 'high') {
  const recent = await countRecentHighRisk(account.id, '15m');
  if (recent >= 5) {
    await lockAccount(account.id);
    await notifyOwner(account.email);
  }
}

The layered picture

  • Layer 1 — passwords + breach checks: stop credential stuffing at the door.
  • Layer 2 — IP risk (GeoQ): flag anomalous origin; trigger step-up. The risk score gives you one number to threshold.
  • Layer 3 — MFA / step-up auth: the real gate for risky sessions.
  • Layer 4 — behavioural + device: for the highest-value accounts.

IP signals make layers 2 and 3 cheaper and smarter — applying friction only when it's warranted, so normal logins stay frictionless.

Get started

See the IP fraud detection API, read the quickstart, and grab a free API key (no card).

Signals are probabilistic, not facts. Don't make a sole-basis automated decision about a person — see the acceptable use policy.

Keep reading

Start with the free tier. No card.

1,000 lookups a day, every signal, the same transparent risk score. Upgrade only when you outgrow it.