IP Risk Level API
You need a reliable way to score an IP’s fraud risk in real time so you can block or challenge suspicious sessions before they reach sensitive endpoints. By the end of this guide, you will be able to query ipXapi’s IP Risk Level endpoint, interpret the risk_level in responses, and integrate it into your security pipeline using curl and Python.
What the IP Risk Level API does
The IP Risk Level lookup from ipXapi returns a per-IP fraud_score and, crucially, a categorical risk_level you can use to drive security decisions (for example, blocking, rate-limiting, or step-up authentication). The endpoint operates over HTTPS, requires a Bearer token, and responds with JSON including operator and location context that can help with anti-abuse heuristics.
In this guide we will stick to the officially documented fixture IP and the exact endpoint path so you can copy and ship without guesswork.
Endpoint and authentication
Endpoint path: /api/fraud-score
- Base: https://ipxapi.com
- HTTP method: GET
- Query parameter: ip (the IPv4 address you want to evaluate)
- Auth header: Authorization: Bearer YOUR_API_KEY
- Accept header: application/json
Management and control plane: MCP (use this for account and configuration functions referenced from the docs; the /mcp path on the main domain does not host this content).
Quickstart with curl (official sample)
Use the following request as a known-good probe. Replace the Authorization value with your own key when you run it against your account:
curl "https://ipxapi.com/api/fraud-score?ip=8.8.8.8" -H "Accept: application/json" -H "Authorization: Bearer YOUR_KEY"
Official JSON response (fixture)
The following JSON is the documented product fixture for the same endpoint and IP:
{
"ip": "8.8.8.8",
"fraud_score": 0,
"risk_level": "low",
"risk_label": "Low Risk",
"is_high_risk": false,
"operator": {
"organization": "Level 3",
"isp": "Google LLC",
"asn": "15169",
"hostname": "dns.google"
},
"location": {
"country_code": "US",
"city": "Mountain View"
},
"datacenter": {
"is_datacenter": true
}
}
Field highlights you will typically use:
- risk_level: Categorical risk classification to drive decisions (e.g., low, medium, high).
- fraud_score: Numeric indicator that can help you set internal thresholds; pair it with risk_level if you need finer control.
- is_high_risk: Boolean shortcut for a “blocklist-mode” gate.
- operator.*, location.*, datacenter.is_datacenter: Context to refine challenges or adjust trust for automation and hosting environments.
Note: Live responses can differ from fixtures. Do not assume the sample represents your users’ IPs.
Python example: calling /api/fraud-score and acting on risk_level
The snippet below shows how to call the endpoint, parse the response, and branch on risk_level. It uses the same path and request semantics as the curl sample:
import os
import sys
import json
import requests
from typing import Literal
API_BASE = "https://ipxapi.com"
API_PATH = "/api/fraud-score"
API_KEY = os.getenv("IPXAPI_KEY", "YOUR_API_KEY") # replace with your key or set env var
TIMEOUT = 6 # seconds; tune per your SLA and retry policy
RiskLevel = Literal["low", "medium", "high"] # use categorical risk_level in gating logic
def fetch_risk(ip: str) -> dict:
url = f"{API_BASE}{API_PATH}"
headers = {
"Accept": "application/json",
"Authorization": f"Bearer {API_KEY}",
}
params = {"ip": ip}
resp = requests.get(url, headers=headers, params=params, timeout=TIMEOUT)
# Surface HTTP errors with context
try:
resp.raise_for_status()
except requests.HTTPError as e:
# Log response text for troubleshooting without leaking secrets
sys.stderr.write(f"ipXapi error: {resp.status_code} {resp.text[:500]}\\n")
raise e
return resp.json()
def decide_action(payload: dict) -> str:
# Primary switch on risk_level; do not assume other fields always exist
rl: RiskLevel = payload.get("risk_level", "high") # fail-closed as high
if rl == "low":
return "allow"
elif rl == "medium":
return "challenge" # e.g., CAPTCHA or MFA
else:
# includes "high" or unexpected/missing values
return "block"
if __name__ == "__main__":
test_ip = "8.8.8.8" # fixture for manual testing; replace in production flows
data = fetch_risk(test_ip)
action = decide_action(data)
print(json.dumps({"ip": data.get("ip"), "risk_level": data.get("risk_level"), "action": action}, indent=2))
Implementation notes:
- Always branch on the categorical risk_level for clarity. Keep your gating logic simple and auditable.
- Use a modest timeout and retries at the edge of your stack; on client-facing paths, prefer fail-safe behavior (e.g., default to “challenge”).
- Avoid logging sensitive headers; redact Authorization in server logs.
Integrating risk signals into security workflows
Most teams start by mapping risk_level to a three-tier action matrix. Keep the switch simple and deterministic so it is easy to audit and debug. Examples:
- low → allow with normal rate limits.
- medium → allow but require step-up (MFA, email verify) or tighten rate limits.
- high → block or require a hardened verification path.
Where applicable, use context fields to refine secondary rules. For example, you might reduce trust for datacenter.is_datacenter true when processing account creation or credential stuffing-prone flows. Similarly, operator.hostname and asn can be logged for anomaly detection dashboards.
Operational guidance: caching, retries, and consistency
IP intelligence responses change over time as threat signals evolve. A practical approach is to cache by IP for a short TTL in your application tier to lower latency and preserve quota. A common range is minutes to hours depending on how quickly you need to react to abuse and your expected traffic churn across distinct IPs.
- Caching key: the input IP address.
- Cache value: the parsed response object or only the risk_level plus a timestamp.
- Expiry strategy: fixed TTL; consider stale-while-revalidate if your system can tolerate slightly outdated risk_level during background refresh.
For reliability, wrap calls with bounded retries on transient network errors. If your control plane uses circuit breakers, prefer failing to “challenge” rather than silently allowing a risky request when the API is unavailable.
Testing with the fixture IP and moving to production
Start with the documented fixture IP 8.8.8.8 to verify your integration path, headers, and parsing. Ensure you:
- Send the Authorization header with Bearer YOUR_API_KEY.
- Pass the ip query parameter with the address under evaluation.
- Parse JSON using standard libraries and prefer defensive coding if fields are missing.
Once your request/response loop works with the fixture, test with a mix of real IPs from your logs in a development environment. Do not hardcode assumptions from the fixture; live flags can change and may differ for your data.
Security posture and privacy notes
Keep risk checks on the server side to protect your key and headers. If you must evaluate on the client, proxy the request through your backend and add your own auth there. Rotate keys periodically and restrict access to logs containing response bodies if they include operator or location details you consider sensitive internally.
When recording outcomes for analytics, store the categorical risk_level and the decision you took, not the full payload, unless you have a retention policy that covers operator and location fields.
Handling errors and unexpected responses
Common categories to prepare for:
- Authentication failures: Verify the Bearer token is present and valid. Avoid retry loops on 401/403.
- Client mistakes: Validate IP format before calling to reduce error volume.
- Transient issues: Apply short backoff and a small number of retries for network timeouts or 5xx responses.
On parse errors, treat the IP as unknown and choose a conservative path (e.g., “challenge” rather than unconditional allow). Send structured error metrics so you can alert on elevated failure rates.
Deployment and observability
Add request counters and latencies for the /api/fraud-score call to your dashboards. Break out success vs. error rates and track the distribution of risk_level over time. These metrics help you calibrate rate limits and spot abuse campaigns as they spike.
If you run multiple services that need risk checks, centralize the call in a small library or an internal gateway to standardize timeouts, retries, caching, and logging. This reduces drift between teams and simplifies incident response.
Account, pricing, and limits
Basic is $29.99/month. The trial is 7 days or 50 requests. For full plan details and the latest instructions, see the Documentation. When you are ready to get a key, use Register.
Reference: request checklist
- URL: https://ipxapi.com/api/fraud-score
- Method: GET
- Query: ip=8.8.8.8 (replace with the IP you are evaluating in production)
- Headers:
- Accept: application/json
- Authorization: Bearer YOUR_API_KEY
- Primary field to read: risk_level
FAQ
Can I rely solely on fraud_score or should I gate on risk_level?
Use risk_level as the primary switch because it encapsulates the vendor’s categorical assessment. If you need fine-grained control, combine risk_level with fraud_score thresholds, but keep the decision tree simple.
How should I cache results to balance cost and freshness?
Cache by IP with a short TTL. The appropriate TTL depends on how quickly you need changes to take effect; many teams start with minutes and adjust based on abuse responsiveness and traffic mix.
Does the fixture IP represent my traffic?
No. The documented fixture is for testing your integration only. Live responses will differ for your users’ IPs, and flags can change over time.
Where do I manage my account and configuration?
Use the MCP endpoint noted in the docs for management functions.
What should I do if the API call fails during a login or checkout?
Fail safe: default to a “challenge” flow rather than allowing a risky action without evaluation. Log the failure, include minimal context, and retry with backoff if the user persists.
Next steps
Get an API key, run the curl fixture to confirm your headers, then plug the Python snippet into your auth or anti-abuse middleware and branch on risk_level. Start your trial or pick the Basic plan via Register, and keep the docs handy here: Documentation.
