IP risk lookup
Identify proxy, VPN, dial-up pool, cloud phone and datacenter addresses. Returns a risk score, network ownership and district-level geolocation. Risk data refreshes every 10 seconds.
Risk signals
| Signal | Verdict | Last seen |
|---|
Network
Location
Proxy exits observed just now
Exits our own probes confirmed were still working within the last hour. The score answers a different question — how strong the currently verifiable evidence is, decaying as it ages. “Confirmed working just now” and “score is not high” can both be true. Click any row to look it up.
Three capabilities
One consistent stance: every answer is a judgement that expires, not a permanent label.
IP ranges and risk mix by country
Address-range ownership broken out by country and region, the residential/datacenter mix, the main operators and ASNs, and how many proxy-type addresses we captured recently. Refreshed daily with the geolocation database.
All 244 countries and regions →
Not sure how to read these signals? How to detect a proxy, VPN or datacenter IP — what each signal means, and what it cannot tell you.
Developer API
The same profiling capability, callable from your own risk system. Try it without registering; sign in to create a key and raise the limit.
https://ip99.com/v1/ip/{ip}# No key needed (anonymous allowance)
curl https://ip99.com/v1/ip/8.8.8.8
# With a key you create yourself, the allowance is per account
curl -H "X-API-Key: YOUR_KEY" https://ip99.com/v1/ip/8.8.8.8
To ask what the risk state was at a past moment (post-incident review, chargeback arbitration),
use ?at= on the Pulse endpoint:
GET /pulse/v1/ip/{ip}?at=2026-08-26T13:34:36Z (RFC3339, up to 30 days back;
the returned computed_at is exactly the moment you asked for). The profile endpoint
on this page answers for now only and does not accept at.
Pulse is professional-tier only: without a professional key it answers
403 professional_required, while the free profile stays open at /v1/ip;
for history, contact sales.
How to read the fields — especially a score of 0
The response contains no Chinese. Place names, usage types and risk types come back as standard codes or stable slugs, so your parsing layer never has to deal with Chinese text.
| Field | What it means |
|---|---|
risk.score | 0–100. The freshness and strength of verifiable risk evidence, decaying as that evidence ages. It is not a probability that the address is an attacker. Same source and same value as score on /pulse/v1/ip — one address, one score. |
risk.level | high / medium / low / none, derived from risk.score (0=none, 1–29=low, 30–69=medium, 70–100=high). none means we hold no currently verifiable evidence — not that the address is safe. Know that before you allow on a 0. |
score_semantics / computed_at | The scoring-semantics token and the moment this score was computed for. Scores decay with evidence age, so which moment was scored is part of what makes the answer checkable: the same address scoring differently a few hours apart is normal. |
evidence_state | active: fresh evidence that still scores. stale: seen before, but past its freshness window and scoring 0 — usable as a weak signal, not as a blocking reason on its own. none: never seen — possibly a coverage gap, and not the same as safe. Route on this field rather than on the score alone. |
risk.tag_details[].last_seen | When that class of evidence was last captured, as an RFC3339 timestamp with a UTC offset (e.g. 2026-08-20T10:51:05+08:00). A tag can still be present while the score has decayed to 0 — that means the evidence expired, not that the address is clean. Judge by how long ago last_seen was. |
signals.* | Boolean signals. hosting / mobile are derived from the network usage type and are not risks in themselves; the rest map one-to-one onto tags. |
network / geo | Address ownership, in the same shape as the professional tier of /pulse/v1/ip: network.asn, network.usage_type (IDC/DYN/MOB/GTW/EDU/GOV/CDN/ORG/DNS/NET/COM/BOGON); geo.continent (AS/EU/NA/SA/AF/OC/AN), geo.country (ISO 3166-1 alpha-2), geo.lat/lon/tz. Chinese addresses also carry geo.subdivision (ISO 3166-2) and geo.admin_code (GB/T 2260, six digits, down to district); everywhere else gets Latin geo.region / geo.city. Operator names are not returned — the machine-readable identity is asn, which you can resolve against the public registries. |
| Tier | Daily allowance | How to get it |
|---|---|---|
| Anonymous | — | Just call it, no key needed |
| Free account | — | Sign in and create an API key |
| Professional | Custom | Adds days observed, distinct sources and a resource-pool handle (an anonymous handle: stable within your account, not joinable across accounts) on top of the free fields, and lets you score against a past moment. Capture timestamps require a data-processing agreement. Contact sales to enable |
| Enterprise | Custom | Contact sales |
Web lookups and API calls share one daily allowance — counted per public IP when anonymous, per account once signed in. The professional tier is a data tier and is independent of the quota tier: enterprise does not automatically include professional fields. All of the above means calling our public service; if the data must never leave your own machines, see Tide or Pulse self-hosted (each priced separately).
Contact sales
Higher allowances, self-hosted deployment or custom labels — leave your details and we will get back to you.