Most provider overviews list "9 ways to use IP geolocation for security." They describe the mechanisms correctly but stop there — no code, no thresholds, no implementation guidance. This guide goes further: every technique includes the API call, the response fields that matter, and how to act on them.
What IP Intelligence Returns
Every technique below draws on one or more fields from a single IP lookup. Here is the full response structure:
curl "https://api.geoiphub.com/v1/lookup?ip=185.220.101.47" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"ip": "185.220.101.47",
"country": "DE",
"region": "Hesse",
"city": "Frankfurt am Main",
"latitude": 50.1109,
"longitude": 8.6821,
"timezone": "Europe/Berlin",
"asn": 60729,
"asn_org": "Zwiebelfreunde e.V.",
"asn_type": "hosting",
"is_datacenter": true,
"is_residential": false,
"is_mobile": false,
"is_vpn": false,
"is_proxy": false,
"is_residential_proxy": false,
"is_tor": true,
"tor_exit": true,
"on_blocklist": true,
"blocklist_count": 4,
"blocklist_categories": ["spam", "scanner", "brute_force"],
"abuse_reports_30d": 12,
"risk_score": 94,
"risk_factors": [
"tor_exit_node",
"abuse_reports_recent",
"multi_blocklist",
"datacenter_asn"
],
"reputation": "very_low",
"confidence": 0.97
}
One request. Everything you need for every technique below.
Technique 1: Block Known Malicious IPs at the Perimeter
The cheapest defense: reject requests from IPs with documented abuse history before they touch your application. The on_blocklist, blocklist_count, and abuse_reports_30d fields contain this data.
def check_ip_at_entry(ip: str) -> dict:
data = geoiphub_lookup(ip)
# Hard block: multi-category blocklist with recent abuse
if data["blocklist_count"] >= 3 and data["abuse_reports_30d"] > 5:
return {"action": "block", "reason": "multi_blocklist_recent_abuse"}
# Hard block: known Tor exit node (in transaction flows)
if data["is_tor"] and data["tor_exit"]:
return {"action": "block", "reason": "tor_exit_node"}
return {"action": "continue", "risk_score": data["risk_score"]}
Calibrate the blocklist threshold by flow. A password reset form should block at blocklist_count >= 2. A public content endpoint might only block at blocklist_count >= 5. The confidence field (0.0–1.0) tells you how many independent sources corroborated the verdict — only block on high-confidence signals.
Technique 2: Detect and Restrict VPN and Proxy Traffic
Anonymization services hide the user's real location and identity. Commercial VPNs have millions of legitimate users, so blocking all VPN traffic is too broad for most products. Proxies and Tor exits in transaction flows have almost no legitimate use case.
def anonymization_response(ip: str, flow: str) -> str:
data = geoiphub_lookup(ip)
# Tor exits: block in all sensitive flows
if data["is_tor"]:
return "block" if flow in ["checkout", "login", "signup"] else "challenge"
# SOCKS/HTTP proxies: almost always abuse tooling
if data["is_proxy"]:
return "block"
# Residential proxies: very high risk, challenge everywhere
if data["is_residential_proxy"]:
return "challenge_strong"
# Commercial VPN: challenge in sensitive flows, allow in low-risk
if data["is_vpn"]:
return "challenge" if flow in ["checkout", "payment"] else "allow_log"
return "allow"
The detection mechanism behind each flag:
is_vpn: IP matched against published provider infrastructure lists (NordVPN, ExpressVPN, Mullvad, etc.) and active OpenVPN/WireGuard handshake probingis_proxy: Port probing on SOCKS5 (port 1080) and HTTP proxy (ports 3128, 8080) greeting sequencesis_residential_proxy: Cross-referencing against proxy network advertisement databases and IP reuse pattern analysisis_tor: Match against the public Tor consensus directory exit node list
Technique 3: Enforce Geographic Restrictions
Compliance requirements, licensing agreements, and sanctions programs sometimes require hard geo-restrictions — blocking access from specific countries or regions. The country field supports this, but the check must also catch users bypassing restrictions with VPNs.
BLOCKED_COUNTRIES = {"KP", "IR", "CU", "SY"} # sanctions compliance example
RESTRICTED_FLOWS = {"checkout", "download", "api_access"}
def check_geo_compliance(ip: str, flow: str) -> dict:
data = geoiphub_lookup(ip)
# Country-level block
if data["country"] in BLOCKED_COUNTRIES and flow in RESTRICTED_FLOWS:
return {"action": "block", "reason": "geo_compliance"}
# VPN bypass attempt: the apparent location may not be real
if data["is_vpn"] and flow in RESTRICTED_FLOWS:
# You cannot trust the geolocation when a VPN is active
return {"action": "block", "reason": "geo_verification_impossible"}
return {"action": "allow"}
The critical point most overviews omit: VPN detection is required for geo-restriction enforcement to be meaningful. If you block country: IR but allow is_vpn: true requests, users in restricted jurisdictions simply connect through a VPN server in Germany and your block fails. Effective geo-compliance requires both fields together.
Technique 4: Flag Impossible Travel on Account Logins
Impossible travel is one of the most reliable signals for account takeover. A human cannot log in from London and Singapore within 30 minutes — one of those sessions is from stolen credentials or a compromised device.
import math
from datetime import datetime, timedelta
def haversine_km(lat1, lon1, lat2, lon2) -> float:
R = 6371
dlat = math.radians(lat2 - lat1)
dlon = math.radians(lon2 - lon1)
a = math.sin(dlat/2)**2 + math.cos(math.radians(lat1)) * \
math.cos(math.radians(lat2)) * math.sin(dlon/2)**2
return R * 2 * math.asin(math.sqrt(a))
def check_impossible_travel(user_id: str, current_ip: str) -> dict:
current = geoiphub_lookup(current_ip)
previous = get_last_login(user_id) # {ip, latitude, longitude, timestamp}
if not previous:
return {"action": "allow"}
distance_km = haversine_km(
previous["latitude"], previous["longitude"],
current["latitude"], current["longitude"]
)
hours_elapsed = (datetime.now() - previous["timestamp"]).total_seconds() / 3600
required_hours = distance_km / 900 # ~commercial aircraft speed
if distance_km > 500 and hours_elapsed < required_hours:
return {
"action": "block_session_flag_account",
"reason": "impossible_travel",
"distance_km": round(distance_km),
"hours_elapsed": round(hours_elapsed, 1),
"hours_required": round(required_hours, 1)
}
return {"action": "allow"}
Two calibration notes: First, VPN users will trigger impossible travel by switching server locations — check is_vpn before logging the location as ground truth; a VPN location is not a real location. Second, mobile users on CGNAT share IPs, so geolocation precision at city level is lower — set a minimum distance threshold of at least 200 km before flagging to avoid false positives from CGNAT-induced location drift.
Technique 5: Block Automated Scanning and Scraping
Credential stuffing attacks, vulnerability scans, content scrapers, and price comparison bots overwhelmingly originate from cloud and datacenter IPs. Real people use residential ISPs or mobile networks. A checkout from AS16509 (Amazon Web Services) has no plausible legitimate user behind it.
def is_likely_automated(ip: str, flow: str) -> bool:
data = geoiphub_lookup(ip)
# Datacenter IPs at consumer flows are structurally suspicious
if data["is_datacenter"] and flow in ["login", "checkout", "signup"]:
return True
# Known scanner or bot fingerprints
if data.get("is_known_scanner") or data.get("is_bot"):
return True
# High risk score with datacenter context
if data["risk_score"] > 70 and data["asn_type"] in ["cloud", "hosting"]:
return True
return False
The ASN types that indicate infrastructure rather than real users:
cloud: AWS, Google Cloud, Azure, OVHhosting: dedicated servers, VPS providers (Vultr, Hetzner, DigitalOcean)cdn: Cloudflare, Akamai, Fastly — these are edge nodes, not usersvpn: ASNs with documented VPN server history
The asn_type: "isp" or asn_type: "mobile" types are baseline legitimate — that is where real people connect from.
Technique 6: Rate Limit and Throttle by Network Context
Rate limiting is more effective when calibrated to the infrastructure type behind the IP. A single residential IP can be a CGNAT address shared by hundreds of users — throttling it aggressively blocks real people. A datacenter IP is almost certainly one automated client — throttle it severely.
RATE_LIMITS = {
"isp": {"requests_per_minute": 60, "action_on_exceed": "delay"},
"mobile": {"requests_per_minute": 120, "action_on_exceed": "delay"}, # CGNAT = many users
"cloud": {"requests_per_minute": 10, "action_on_exceed": "block"},
"hosting": {"requests_per_minute": 5, "action_on_exceed": "block"},
"vpn": {"requests_per_minute": 20, "action_on_exceed": "challenge"},
"cdn": {"requests_per_minute": 100, "action_on_exceed": "delay"}, # could be your own edge
}
def get_rate_limit(ip: str) -> dict:
data = geoiphub_lookup(ip)
asn_type = data.get("asn_type", "isp")
limits = RATE_LIMITS.get(asn_type, RATE_LIMITS["isp"])
# Escalate if high risk score regardless of ASN type
if data["risk_score"] > 75:
limits = {"requests_per_minute": 3, "action_on_exceed": "block"}
return limits
Technique 7: Detect High-Risk Countries at Checkout
Country-level fraud risk varies significantly by product and market. For payment fraud specifically, certain country-to-billing-address mismatches are a high-signal pattern — a card with a UK billing address used from an IP geolocated to a high-fraud-volume region.
def assess_checkout_geo_risk(ip: str, billing_country: str) -> dict:
data = geoiphub_lookup(ip)
ip_country = data["country"]
# VPN blocks the check — cannot trust the apparent country
if data["is_vpn"] or data["is_proxy"] or data["is_residential_proxy"]:
return {
"risk_level": "high",
"reason": "country_unverifiable_due_to_anonymizer",
"action": "require_3ds"
}
# Country mismatch between IP and billing address
if ip_country != billing_country:
return {
"risk_level": "elevated",
"reason": f"ip_country_{ip_country}_billing_{billing_country}",
"action": "require_3ds"
}
return {"risk_level": "standard", "action": "allow"}
Do not build a hardcoded block list of "risky countries" and maintain it manually. Use the IP's risk signals — anonymization status, abuse history, ASN type — to detect the infrastructure behind attacks rather than the geography it appears to come from. Sophisticated attackers deliberately route through clean-looking IPs in low-risk country geolocation pools.
Technique 8: Filter Invalid Traffic Before It Reaches Analytics
Automated bots, crawlers, and scrapers contaminate your analytics data and, more damagingly, your paid ad conversion signals. Filtering at the IP intelligence layer before events register in GA4 or your Smart Bidding model protects signal quality.
def should_record_session(ip: str) -> bool:
data = geoiphub_lookup(ip)
# Known good bots (Googlebot, Bingbot) — exclude from analytics but don't block
if data.get("is_known_good_bot"):
return False
# Datacenter IPs on consumer flows are not users
if data["is_datacenter"] and data["risk_score"] > 50:
return False
# Anonymizers with no conversion value to PPC
if data["is_tor"] or data["is_proxy"]:
return False
# Very high risk scores — likely automated regardless of IP type
if data["risk_score"] > 85:
return False
return True
For paid traffic specifically: any session from a datacenter or known bot IP that converts triggers an invalid conversion event in Google Ads. Those corrupt the Smart Bidding model because the model learns that "sessions from [signal cluster]" don't convert — then under-bids for real buyers who share some of those signals. Paid traffic has its own playbook, and it starts by abandoning the IP exclusion list — see how to detect click fraud by IP address.
The Full Decision Matrix
What IP Geolocation Cannot Catch Alone
IP geolocation is a first-pass filter. It misses:
Residential proxies with clean reputations. An IP that was added to a proxy pool yesterday has no abuse history and passes blocklist checks. Detection requires behavioral signals that IP intelligence alone cannot supply — device fingerprint anomalies, session timing patterns, interaction rate.
Compromised human accounts. If an attacker has valid credentials and uses a clean residential IP in the same country as the victim, there is nothing in the IP data to flag. Behavioral signals — typing speed, navigation patterns, purchase history divergence — are needed.
Sophisticated targeted attacks. A targeted attacker who researches your defenses will use a clean residential IP in the same city as the victim. They pass every IP-level check. Email verification and device binding are the defenses here.
The correct model: IP intelligence filters the volume of automated and low-sophistication attacks at near-zero cost per request, so that more expensive checks (device fingerprinting, behavioral analysis, manual review) can focus on the remainder.
Implementation Notes
Cache aggressively. IP data changes infrequently within a single session. Cache per IP for the duration of the session (15–30 minutes) with a short TTL (1 hour for security-critical data, 24 hours for basic geo-fields). One lookup per IP per session is the practical cost model.
Log the full response, not just the verdict. When a block fires, you want to know which signal triggered it. Store the risk_factors array and the raw risk_score with every decision — that is how you identify false positives and tune thresholds.
Tune thresholds per flow, not per site. A password reset flow deserves a lower block threshold than a blog read. Define thresholds in configuration, not in code, so your security team can adjust without a deployment.
FLOW_THRESHOLDS = {
"checkout": {"block_above": 75, "challenge_above": 50},
"login": {"block_above": 80, "challenge_above": 55},
"signup": {"block_above": 85, "challenge_above": 60},
"api_read": {"block_above": 90, "challenge_above": 75},
}
The GeoIPHub free tier covers 10,000 lookups per month with all fields returned — infrastructure type, anonymization detection, and risk score included. No separate subscription for "threat data" or "proxy detection." The full response is one endpoint.
# Test any IP free — no signup required for the first 100 requests
curl "https://api.geoiphub.com/v1/lookup?ip=8.8.8.8"
Start Scoring Every IP in Real Time
GeoIPHub gives fraud, security, and engineering teams a single API for IP geolocation, VPN & proxy detection, threat intelligence, and an explainable 0–100 risk score.
Get Your Free API Key
Sign up in minutes — no credit card required. Upgrade only when you need more volume.
Frequently Asked Questions
Can IP geolocation prevent cyber attacks?
IP geolocation is one layer of defense, not a complete solution. It can block requests from known malicious infrastructure, detect anonymization attempts, enforce geo-restrictions, flag login anomalies from impossible travel, and filter automated traffic — all before your application layer processes the request. What it cannot do is catch sophisticated attackers using residential proxies with clean reputations, or distinguish a real user from a compromised human device. Use it as a first-pass filter combined with behavioral and device signals.
What types of cyber attacks does IP geolocation help prevent?
IP geolocation is most effective against: credential stuffing attacks (bots hitting login forms from cloud and proxy IPs), account takeover via impossible travel (login from Berlin then Seoul in 5 minutes), geographic compliance violations (users bypassing geo-restrictions with VPNs), automated scanning and scraping from datacenter IPs, and click fraud or invalid traffic from known bot infrastructure. It is less effective against targeted attacks by sophisticated actors who use residential proxies to blend in with legitimate users.
How do I check if an IP is from a VPN or proxy?
An IP geolocation API with anonymization detection returns boolean fields — is_vpn, is_proxy, is_tor, is_residential_proxy — alongside the geolocation data. VPN detection works by cross-referencing the IP against published provider infrastructure lists and active protocol probing. Proxy detection uses port probing. Tor exit node detection uses the public Tor consensus directory. Residential proxy detection requires behavioral signals: IP appearance in proxy network advertisements and abnormal reuse patterns.
What is impossible travel detection and how does it work?
Impossible travel detection flags account logins from two geographically separate locations within a time window that is physically impossible for a human to travel between. Example: a user logs in from London at 14:00, then from Singapore at 14:30. The 5,500-mile distance requires at minimum 13 hours of flight time, so either the London or Singapore login is from a different device or a stolen session. Implementation: store the IP geolocation at each login, calculate distance and elapsed time between consecutive logins, flag pairs where distance / time > 900 km/h (roughly the speed of commercial aircraft).
Should I block all traffic from certain countries?
Country-level blocking is a blunt instrument with significant collateral damage. Before blocking an entire country, verify whether you have legitimate users there — a block you set once will also hit those users. More targeted alternatives: escalate to step-up verification for high-risk countries on sensitive flows (payment, password reset), use geo-restriction only where legally or contractually required, and combine country data with other signals (datacenter ASN, VPN detection) to target the infrastructure being abused rather than the population it appears to come from.
What is the difference between IP geolocation and IP intelligence for security?
IP geolocation returns location fields: country, region, city, coordinates. IP intelligence returns the full dossier: location plus infrastructure type (residential, datacenter, mobile), anonymization status (VPN, proxy, Tor, residential proxy), abuse history, blocklist presence, threat classifications, and a synthesized risk score. For security use cases, you almost always want IP intelligence, not just geolocation. The country field alone tells you almost nothing about whether a request is legitimate.

