IPure IP purity check

Developers / agents

API docs

Everything on a report page is available as JSON: one call returns the score, proxy / VPN / Tor detection, blocklists and abuse history, per-use-case suitability, every deduction with its source, and the limits of the data. No API key, no sign-up. The machine-readable description is at /openapi.json; the site summary for models is at /en/llms.txt.

Endpoints

One report, three shapes

GET /en/ip/{ip}
The report as a web page, for people, search engines and AI browsing tools.
GET /en/ip/{ip}.json
The full report as JSON. Identical to /api/lookup?ip={ip}&lang=en — same limits, same allowance.
GET /en/ip/{ip}.txt
A 72-column plain-text report. No HTML or JSON parsing needed.

Examples: /en/ip/8.8.8.8 · /en/ip/8.8.8.8.json · /en/ip/8.8.8.8.txt. Drop the /en prefix for the Chinese versions. Some AI browsing environments refuse API-style URLs with query parameters; the path-style addresses above are not affected, and every report page also embeds the same JSON in script#ipure-report. GET /api/myip?format=text echoes the caller's public IP.

Limits

Who can call it, and how much

  • IPs already in the database return instantly, cost nothing and can be requested by any client.
  • IPs not yet in the database trigger live queries to several upstream sources. Scripts and agents get 5 such lookups per source IP per day without verification (there is also a site-wide daily total); the remainder is in the x-open-budget-remaining header. When it runs out the API returns 403 with code = verification_required and a reportUrl: open it in a browser once and the IP is in the database from then on. Site-wide, 15 unverified lookups are admitted per minute; beyond that you get 429 with code = open_rate_limited — wait for Retry-After and retry.
  • Rate limits: 30 requests / minute; 10 first-time lookups of new IPs / minute. Over the limit returns 429.
  • Freshness: stored reports carry queriedAt and a stale flag. An IP's nature rarely changes, so a stored report is usually fine to use as is.
  • Bulk or scheduled checks: please get in touch via the feedback button on ipure.dev rather than scanning ranges.

Fields

What the response contains

ip / versionNormalised address and IP version (4 / 6)
queriedAtWhen the report was generated. With source = store this is the original check time; read it together with stale
sourcefresh (live lookup) · cache (in-process) · store (database)
usageTyperesidential · mobile · business · hosting · education · government · unknown
nativeTypenative · broadcast (registered in one country, used in another) · unknown
flagsisProxy / isVpn / isTor / isHosting / isMobile / isRelay / isBogon / isSearchEngineBot
flagAgreementHow many data sources agree on each flag. A single-source flag counts at half weight in the score
vpnOperatorFor known commercial VPNs: name, anonymity, popularity, protocols, logging, freeAccess. Otherwise null
risk.purityPurity 0-100; higher is cleaner
risk.level / label / verdictSix bands: pristine · clean · neutral · suspicious · risky · dangerous, with a one-line verdict
risk.confidencelow / medium / high — how much data source coverage backs the score. Read score and confidence separately
risk.factors[]Where every point came from: label, category, points (positive deducts, negative adds back), detail, floor (a minimum risk that cannot be offset)
scenarios[]Suitability per use case: ai · social · streaming · gaming · ecommerce · email, each with score, level, levelLabel and reason. score is null when level is restricted or not_applicable
scenarioApplicablefalse means the address is public infrastructure (a public DNS resolver, a search engine crawler), not anyone's egress IP; the reason is in scenarioNote
blocklists[]Each public blocklist: listed; benign (listed but not a risk, e.g. a PBL residential declaration); unavailable (could not be queried, so unknown)
abuse[]Abuse reports (score, reports) and recorded attack activity (attacks.byType: login attempts, bulk registration, vulnerability probing …)
exposure / sharingNetwork exposure (open ports, known vulnerabilities) and sharing (devices observed on the address / in the subnet)
sources[]Status of each data source for this report: ok, ms, error, skipped. A failed source is not a clean result
feedbackReal-world experience ratings (1-5, 5 is best) per use case from visitors who were actually using this IP. Shown once a use case has 3 ratings. Independent of the score
unknowns[]What cannot be determined from an IP alone — see below. Always pass these on
reportUrlThe human-readable report. Cite it with any conclusion
lang / untranslatedEnglish responses carry lang = en. untranslated lists any deduction ids that had no English text (normally empty)

Limits of the data

What an IP check cannot tell you

Conclusions reflect public and partner data at query time. They are not a guarantee of account safety or platform access.

  • Each platform's internal risk labels

    Platforms keep their own IP reputation data and ban records and do not publish them. No hit in public sources does not mean a platform has nothing on this IP.

  • Whether the IP is truly exclusive

    Sharing is only the number of devices observed in the same subnet. It cannot show who else is using this exit right now, or what they are doing.

  • Which accounts this IP has been tied to

    Account-to-IP links exist only inside each platform. Accounts previously banned on this IP are invisible to us.

  • Device, browser and behaviour

    Risk systems look at IP + device fingerprint + behavioural rhythm together. A clean IP with an odd fingerprint or behaviour still gets blocked.

  • Whether the account profile matches the IP

    When sign-up country, phone number, payment method, language or time zone disagree with the IP's location, platforms verify further. That is unrelated to IP purity.

Examples

Three ways to call it

curl

curl -s "https://ipure.dev/en/ip/8.8.8.8.json" | jq '.risk.purity, .risk.verdict, [.scenarios[] | {id, score, levelLabel}]'
curl -s "https://ipure.dev/en/ip/8.8.8.8.txt"          # plain text, no parsing

Python

import requests

r = requests.get("https://ipure.dev/en/ip/8.8.8.8.json", timeout=30)
r.raise_for_status()
report = r.json()
print(report["risk"]["purity"], report["risk"]["verdict"])
if not report["scenarioApplicable"]:
    print(report["scenarioNote"])
for s in report["scenarios"]:
    print(s["label"], s["score"], s["levelLabel"], "-", s["reason"])
print("Cannot be determined:", [u["label"] for u in report["unknowns"]])

TypeScript

const res = await fetch("https://ipure.dev/en/ip/8.8.8.8.json");
if (!res.ok) throw new Error(`IPure ${res.status}`);
const report = await res.json();
const ai = report.scenarios.find((s: { id: string }) => s.id === "ai");
console.log(report.risk.purity, ai?.levelLabel, report.vpnOperator?.name ?? "not a known commercial VPN");

Terminal (reports are in Chinese unless you add lang=en)

curl -L "ipure.dev/cli/8.8.8.8?lang=en&color=0"

For agents

When to call it, and when not to

Good fit

“Is this IP clean?” “Can I use this proxy for ChatGPT / signing up on X / an Amazon seller account / Netflix?” “Is it a VPN or data center IP?” “Why do I keep getting flagged?” Also: checking your own egress IP before a network task, or comparing several candidate IPs.

Not a fit

DNS configuration, deployment, connectivity troubleshooting, or anything that needs a platform's internal risk data. When quoting a conclusion, pass on unknowns too, and never turn “no risk signals found” into “safe”.