IP Reputation API: Threat Score and VPN, Proxy, Tor and Abuse Flags for Any IP
Short answer
Send the IP address to GET https://api.iplookupapi.com/v1/info and read the security object: it flags VPN, proxy, Tor, data center, anonymous, bot, abuser, known attacker, spam and iCloud Private Relay addresses and adds a proxy type and a threat score from 0 (no known threat) to 100. The batch endpoint returns the same object for up to 1,000 addresses per request. Security data is part of the Professional plan and up, from $34.99 per month for 650,000 requests.
On this page
- Check an IP’s reputation with one request
- Security fields: what each flag means
- Bot verification and coarse locations
- Use cases: decide in tiers, not on one flag
- Code: look up the security object and decide
- False positives and fair use of IP reputation
- Privacy: IP addresses are personal data under the GDPR
- Plans: which plan includes IP reputation data
An IP reputation API tells you what is known about an address before you trust a request. iplookupapi returns this IP intelligence as the security object of the regular lookup: ten yes/no flags, a proxy type and a threat score, next to network and abuse-contact data. Below are the request, each field, code with an example allow, challenge or review policy, false positives, privacy and plans.
Check an IP’s reputation with one request
Send the address in ip and your key in the apikey header. fields limits the response to the security object, four network fields and the ASN and organization:
curl -H "apikey: YOUR_API_KEY" \
"https://api.iplookupapi.com/v1/info?ip=80.110.0.1&fields=ip,security,network.is_hosting,network.is_mobile,network.is_cgnat,network.as_type,connection.asn,connection.organization"The response below is trimmed from the official sample on the info endpoint documentation. The address belongs to an Austrian ISP, so every flag is false and the threat score is 0:
{
"data": {
"ip": "80.110.0.1",
"connection": {
"asn": 8412,
"organization": "Magenta Telekom GmbH"
},
"network": {
"is_hosting": false,
"is_mobile": false,
"is_cgnat": false,
"as_type": "isp"
},
"security": {
"is_anonymous": false,
"is_datacenter": false,
"is_vpn": false,
"is_bot": false,
"is_abuser": false,
"is_known_attacker": false,
"is_proxy": false,
"is_spam": false,
"is_tor": false,
"proxy_type": "",
"is_icloud_relay": false,
"threat_score": 0
}
}
}Keep the key in the header, because query strings end up in access logs. Always pass the visitor’s address: without ip, the API answers for your server. Behind a load balancer or CDN, find the real client IP and only trust an X-Forwarded-For header that your own proxy set.
Security fields: what each flag means
| Field | Meaning (from the docs) | Typical use | Caution |
|---|---|---|---|
is_anonymous | Tor exit, VPN, open proxy or privacy relay | One check for “traffic is hidden” | Includes privacy relays used by ordinary consumers |
is_datacenter | Data center, cloud, hosting or CDN address | Scripted signups, scraping, API abuse | Also matches your own servers and partners |
is_vpn | Server of a commercial or consumer VPN | Context for geo checks, step-up at login | Many people use a VPN for privacy or work |
is_proxy | Public or open HTTP or SOCKS proxy | Challenge or review | The address can pass to a new user after the proxy shuts down |
is_tor | Tor exit node | Challenge or review on sensitive actions | Many Tor users need it for safety |
is_bot | Verified crawler or monitor published by its operator, or an internet-wide research scanner | Skip analytics, separate bot traffic | Not a “bad bot” flag |
is_abuser | Recently reported for abuse by blocklists | Raise friction | “Recently” means the label can expire |
is_known_attacker | Recently seen attacking (brute force, exploitation, botnets) in threat feeds, or part of a hijacked netblock | Review, protect login and admin areas | Infected home devices share the owner’s IP |
is_spam | Known spam sender | Comment and form spam filters | Shared mail and hosting ranges |
is_icloud_relay | iCloud Private Relay egress address | Treat as privacy relay, not as a VPN | Used by ordinary Apple customers |
proxy_type | tor, vpn, proxy or relay, empty if not anonymous; the first in that order wins | Logging, simple routing | One value only, even if several apply |
threat_score | 0 (no known threat) to 100 in steps of 10 | Tiered decisions | Ranks evidence; not a fraud probability |
On plans with security data, the docs list further keys. reasons holds one short sentence per flag that is set, and last_seen the last day any list saw the address; both help support explain a decision. is_known_good_bot marks addresses that a bot’s operator publishes for its crawlers, monitors or webhook senders. The vpn, proxy, tor and known_attacker objects add a confidence from 0.05 to 1 that says how strongly the lists back the flag. It is not a calibrated probability.
How the threat score is built
The documentation describes threat_score as evidence-based: it combines the anonymity type (Tor exit, open proxy, VPN, relay), internet scanners, data center hosting and threat feeds, weighted by how reliable a feed is and how recently it saw the address. Verified crawlers and allowlisted infrastructure such as public DNS resolvers score 0. The documented examples:
| Situation | threat_score |
|---|---|
| Data center address, nothing else known | 10 |
| VPN server | 30 |
| VPN server in a data center | 40 |
| Tor exit node | 60 |
| Tor exit also reported for attacks | 90 |
Use it as an IP risk score for tiered decisions. It is not an IP fraud score in the sense of a probability that an order is fraudulent.
Network, company and abuse data for risk decisions
The network, company and abuse objects come with every paid plan from Basic and keep you from overreacting to a flag.
| Field | What it tells you | Why it matters |
|---|---|---|
network.is_hosting | Data center, cloud, hosting or CDN network (same data as security.is_datacenter) | A first bot filter from Basic |
network.is_cdn | CDN edge address | Traffic from a CDN edge is the CDN, not the end user |
network.is_mobile | The announcing AS carries only a mobile network | Many users share each address |
network.is_cgnat | Carrier-grade NAT space shared by subscribers | One bad user can taint an address for many |
network.is_relay | Privacy relay egress, with relay.provider | Usually many ordinary users behind it |
network.as_type | isp, hosting, business, education or government | Residential and business traffic look different |
company.type | Same classes, for the holder of the address block | Office network or rented server |
abuse.email, abuse.network | Abuse contact of the registered block | Report attacks to the right network |
Bot verification and coarse locations
Scrapers often claim to be a search engine crawler. Pass the visitor’s User-Agent header (up to 512 characters) in the user_agent parameter, and on plans with security data security.bot.spoofed says whether the address belongs to the operator of the claimed bot: true for a fake, false for a match, null when it cannot be decided. For many addresses, send user_agent in the batch request body, not the query string.
coarse_location=omit removes the city for anycast addresses and for coarse ones, such as mobile, carrier-grade NAT, satellite or relay networks, so you do not store a likely wrong city next to the risk result. It applies to paid plans with the network object.
Use cases: decide in tiers, not on one flag
Combine signals and choose between allow, challenge (CAPTCHA, one-time code, second factor) and review (a person checks the account or order).
- Signup and free-trial abuse. Many trials from
is_datacenteroris_proxyaddresses point to scripts. Ask for email or phone verification. - Login risk. A login from a Tor exit or a known attacker address on an account that usually signs in from a home ISP justifies step-up verification, not a lockout.
- Checkout fraud. Compare the IP country from the IP to country API with the billing country. A VPN plus a country mismatch plus a high order value goes to review; one of them alone usually does not.
- Comment and form spam.
is_spamandis_abuserare good reasons to queue a post for moderation. - Rate limiting. Give data center and proxy addresses a lower request budget.
- Logs and SIEM enrichment. Run log addresses through the batch IP lookup API and store flags, score and abuse contact with each event.
- Admin panels. An allowlist is safer; reputation data adds an alert when someone tries from a Tor exit or attacker address.
Code: look up the security object and decide
All examples run on the server, read the key from IPLOOKUPAPI_KEY, give up after 2 seconds and return no data instead of throwing. decide is an example policy; tune the thresholds on your own traffic.
Warning
Never put the API key in browser JavaScript or a mobile app bundle. The browser calls your backend, and your backend calls the API.
Decide up front what happens when the lookup fails. Fail open (allow) suits signups, comments and most logins, so an outage does not stop customers. Fail closed (challenge, not block) suits payouts, password changes and admin logins. On plans without security data, all security fields are null, and the examples treat that like a failed lookup.
Node.js (fetch)
// Node.js 18+ (built-in fetch). Server-side only: never ship the key to the browser.
const API_KEY = process.env.IPLOOKUPAPI_KEY;
async function getSecurity(ip) {
const params = new URLSearchParams({ ip, fields: 'ip,security' });
try {
const res = await fetch(`https://api.iplookupapi.com/v1/info?${params}`, {
headers: { apikey: API_KEY },
signal: AbortSignal.timeout(2000), // a slow lookup must not block the signup
});
if (!res.ok) return null; // e.g. 403 plan, 404 no data, 429 rate limit or quota
const { data } = await res.json();
return data.security;
} catch {
return null; // timeout or network error
}
}
// Example policy, not a recommendation: tune the thresholds on your own traffic.
function decide(security, { failClosed = false } = {}) {
if (!security || security.threat_score === null) {
return failClosed ? 'challenge' : 'allow'; // no data: fail closed or fail open
}
if (security.is_known_attacker || security.threat_score >= 70) return 'review';
if (security.is_tor || security.is_proxy || security.threat_score >= 40) return 'challenge';
return 'allow';
}
async function main() {
const ip = '80.110.0.1'; // in a request handler: the client IP from your trusted proxy setup
const security = await getSecurity(ip);
console.log(ip, decide(security)); // 80.110.0.1 allow
}
main();For a payout or an admin login, call decide(security, { failClosed: true }).
Python (requests)
import os
import requests
API_KEY = os.environ["IPLOOKUPAPI_KEY"]
def get_security(ip):
"""Return the security object, or None if the lookup fails."""
try:
response = requests.get(
"https://api.iplookupapi.com/v1/info",
params={"ip": ip, "fields": "ip,security"},
headers={"apikey": API_KEY},
timeout=2,
)
response.raise_for_status()
return response.json()["data"]["security"]
except (requests.RequestException, KeyError, ValueError):
return None # timeout, network error, 4xx/5xx or unexpected body
def decide(security, fail_closed=False):
"""Example policy: returns 'allow', 'challenge' or 'review'."""
if not security or security.get("threat_score") is None:
return "challenge" if fail_closed else "allow"
if security["is_known_attacker"] or security["threat_score"] >= 70:
return "review"
if security["is_tor"] or security["is_proxy"] or security["threat_score"] >= 40:
return "challenge"
return "allow"
print(decide(get_security("80.110.0.1"))) # allowPHP (cURL)
<?php
function getSecurity(string $ip): ?array
{
$query = http_build_query(['ip' => $ip, 'fields' => 'ip,security']);
$ch = curl_init('https://api.iplookupapi.com/v1/info?' . $query);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['apikey: ' . getenv('IPLOOKUPAPI_KEY')],
CURLOPT_CONNECTTIMEOUT => 1,
CURLOPT_TIMEOUT => 2,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($body === false || $status !== 200) {
return null; // timeout, network error, 403, 404, 429 and so on
}
return json_decode($body, true)['data']['security'] ?? null;
}
// Example policy: returns 'allow', 'challenge' or 'review'
function decide(?array $security, bool $failClosed = false): string
{
if ($security === null || $security['threat_score'] === null) {
return $failClosed ? 'challenge' : 'allow';
}
if ($security['is_known_attacker'] || $security['threat_score'] >= 70) {
return 'review';
}
if ($security['is_tor'] || $security['is_proxy'] || $security['threat_score'] >= 40) {
return 'challenge';
}
return 'allow';
}
// In a web request, pass the client address you trust, e.g. $_SERVER['REMOTE_ADDR']
echo decide(getSecurity('80.110.0.1')) . PHP_EOL; // allow
The official SDKs wrap the same endpoint if you prefer a client library.
False positives and fair use of IP reputation
IP reputation describes an address, and one address can stand for one person or thousands.
- Shared addresses. Carrier-grade NAT, mobile networks, universities and offices put many users behind one IP, and one infected device gets it reported for all. Check
network.is_cgnat,network.is_mobileandnetwork.as_typebefore acting onis_abuser. - Legitimate anonymity. Corporate VPNs, iCloud Private Relay and Tor protect ordinary users. Use the flags for context, not punishment.
- Change over time. Abuse and attacker flags describe recent activity, and addresses get reassigned. Cache results for hours, not weeks.
- Unknown is not clean. A new proxy is not on any list yet.
falsemeans “not known”, andthreat_score: 0means “no known threat”. - A way through. Never block on IP alone. Offer an alternative to every challenge and a support contact for every review, and log the reason so you can reverse a decision.
See what an IP address tells you about a person, and what it does not.
Privacy: IP addresses are personal data under the GDPR
The GDPR names internet protocol addresses as online identifiers in Recital 30, so treat them as personal data. Recital 49 recognizes processing that is strictly necessary and proportionate for network and information security as a legitimate interest. Mention the check in your privacy notice, store the decision and flags rather than full results, set a retention period, and ask your counsel which rules apply.
Plans: which plan includes IP reputation data
| Plan | Price per month | Requests per month | Data included |
|---|---|---|---|
| Free | $0 | 150 (10 per minute) | Location, connection, time zone, currency |
| Basic | $9.99 | 65,000 | Adds network, company and abuse contact |
| Professional | $34.99 | 650,000 | Adds security data: flags and threat score |
| Enterprise | $74.99 | 2,500,000 | Same data as Professional |
Yearly billing gives you two months free. Use the Free plan to test the request format; the security fields stay null below Professional. A 429 means rate limit or monthly quota, and GET /v1/status shows your remaining quota without counting against it. Compare plans on the pricing page, or register for a free key and run the curl command above.
Frequently asked questions
What is an IP reputation API?
An IP reputation API tells you what is known about an IP address from a risk point of view: whether it belongs to a VPN, proxy, Tor exit or data center, and whether threat feeds and blocklists have recently reported it for attacks, abuse or spam. iplookupapi returns this in the security object of GET /v1/info, together with a threat score from 0 to 100. It describes the address, not the person behind it.
How is an IP's threat score used?
The threat_score in the security object runs from 0 (no known threat) to 100 in steps of 10 and combines anonymity type, scanner activity, data center hosting and threat feeds. Use it to pick a response tier, such as allow, ask for an extra verification step, or hold for manual review, and tune the thresholds on your own traffic. A score of 0 means nothing is known against the address, not that the visitor is trustworthy.
Can an IP reputation API detect VPNs and proxies?
It can flag addresses that are known to belong to them. The security object has is_vpn for commercial or consumer VPN servers, is_proxy for public or open HTTP and SOCKS proxies, is_tor for Tor exit nodes and is_icloud_relay for iCloud Private Relay, plus proxy_type with the main type. An address that no list knows yet is not flagged, so treat a false value as “not known” rather than “not a VPN”.
Should I block traffic based on IP reputation?
Rarely on the IP alone. Shared addresses, carrier-grade NAT, corporate VPNs and privacy relays put many legitimate users behind one IP, so a hard block also stops real customers. Use the flags and the threat score to add friction, such as a CAPTCHA or a one-time code, or to queue a review, and give people a way to reach support.
Is IP reputation data available on the free plan?
No. The security object is part of the Professional plan ($34.99 per month, 650,000 requests) and up. On other plans the object is still in the response, but all its fields are null. The Free plan (150 requests per month) covers location, connection, time zone and currency, and Basic adds network, company and abuse-contact data. See pricing for all plans.
Can I check many IP addresses for reputation at once?
Yes. POST /v1/batch accepts 1 to 1,000 IPv4 and IPv6 addresses in one request and returns the security object for each address on plans with security data. Each valid address counts as one request, duplicates are billed once, and invalid items are listed in errors without being billed. See the batch IP lookup API.
Look up IP addresses in your code
iplookupapi returns the location, provider, time zone and security flags of any IP address as JSON. The free plan includes 150 requests a month.
curl "https://api.iplookupapi.com/v1/info?ip=8.8.8.8" \
-H "apikey: YOUR_API_KEY"