How to Detect Proxies in Python (Step-by-Step)
A Python tutorial: call a proxy detection API, read the proxy type and confidence score, and gate requests — with a reusable function, caching and a Flask example.
This is a hands-on guide to detecting proxies from a Python backend. We'll wrap the proxy detection API in a reusable function, add caching, and gate a Flask route on the result. The same approach works in Django, FastAPI or a plain script.
Prerequisites
You'll need an API key (the free tier is fine for testing) and the requests library:
pip install requests
Keep your key in an environment variable, never in source.
Try a proxy lookup before you code
Step 1: a reusable detection function
import os
import requests
API_BASE = "https://ipscanner.io"
API_KEY = os.environ["IPSCANNER_API_KEY"]
def check_proxy(ip: str) -> dict:
"""Return {'is_proxy': bool, 'type': str|None, 'score': int}. Fails open."""
try:
resp = requests.get(
f"{API_BASE}/v1/proxy/{ip}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=3,
)
resp.raise_for_status()
data = resp.json()
return {
"is_proxy": bool(data.get("proxy")),
"type": data.get("type"),
"score": data.get("score", 0),
}
except requests.RequestException:
return {"is_proxy": False, "type": None, "score": 0} # fail open
Failing open means a detection outage never locks out your users.
Step 2: get the real client IP
Behind a proxy or load balancer, read the forwarded header your infrastructure sets:
def client_ip(request) -> str:
xff = request.headers.get("X-Forwarded-For", "")
if xff:
return xff.split(",")[0].strip() # left-most = original client
return request.remote_addr
Only trust X-Forwarded-For if a proxy you control sets it.
Step 3: gate a Flask route
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.post("/signup")
def signup():
ip = client_ip(request)
result = check_proxy(ip)
if result["score"] >= 70:
return jsonify(error="This network requires verification."), 403
if result["is_proxy"] or result["score"] >= 30:
# add friction instead of blocking: require email/phone verification
request.environ["require_verification"] = True
# ...create the account...
return jsonify(ok=True)
Step 4: add a short-lived cache
import time
_cache: dict[str, tuple[dict, float]] = {}
def check_proxy_cached(ip: str, ttl: int = 600) -> dict:
hit = _cache.get(ip)
if hit and hit[1] > time.time():
return hit[0]
value = check_proxy(ip)
_cache[ip] = (value, time.time() + ttl)
return value
Keep the TTL in minutes — IP risk changes, as covered in what is IP reputation.
Going further
- Add VPN detection for VPN-specific gating.
- Consolidate signals into one IP fraud score.
- Apply the same function on login and checkout, tuning thresholds per action.
Bottom line
Detecting proxies in Python is a single API call: resolve the real client IP, look it up, and act on the type and score. Fail open on errors, cache briefly, and challenge in the mid risk band rather than hard-blocking.