All articles

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.

March 26, 20262 min read

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.

FAQ

Frequently asked questions

Just an HTTP client like requests (or httpx). You call the proxy detection API endpoint and read the JSON response — no special library required.

Related articles