Sign In
Access your IPWhois.net account
No account? Create one
Home / Blacklist / Docs / Python Integration

Python Integration

Flask, Django and FastAPI middleware for IP blocking. Step-by-step setup guide with code examples.
186,817 IPs 8,269 reports Free API
Quick Install
Python 3.7+ Flask Django FastAPI Starlette

Sign in to get your API key for 1,000 req/day and profile attribution.

Download the guard module and install the dependency:

curl -sL https://bl.ipwhois.net/api/python/plugin -o ipwhois_guard.py && pip install requests

Only dependency is requests. Works with Flask, Django, FastAPI or any Python framework. Or just copy the code from below.

Requires: Python 3.7+ pip
What does it do?

A reusable Python module that checks IPs against the IPWhois.net Blacklist with in-memory caching. Use as a Flask decorator, Django middleware, FastAPI dependency, or standalone function in any Python app.

Block
Returns 403 for blacklisted IPs. Works as decorator, middleware or standalone check.
Report
Report malicious IPs back to the blacklist via the report_ip() function.
Core Module
ipwhois_guard.py
import requests from time import time from functools import wraps _cache = {} CACHE_TTL = 3600 # 1 hour MIN_CONFIDENCE = 90 # Block only high-confidence threats API_URL = "https://bl.ipwhois.net/api" def check_ip(ip, min_confidence=MIN_CONFIDENCE): """Check if an IP is blacklisted. Returns threat data or None.""" now = time() if ip in _cache and now - _cache[ip]["ts"] < CACHE_TTL: return _cache[ip]["data"] try: resp = requests.get(f"{API_URL}/check", params={"ip": ip}, timeout=3) data = resp.json() if data.get("listed") and data.get("confidence", 0) >= min_confidence: _cache[ip] = {"data": data, "ts": now} return data else: _cache[ip] = {"data": None, "ts": now} return None except Exception: return None def report_ip(ip, threat_type="brute-force", message="", source="waf"): """Report a malicious IP to the blacklist.""" try: requests.post(f"{API_URL}/report", data={"ip": ip, "type": threat_type, "message": message, "source": source}, timeout=5) except Exception: pass
Flask
app.py
from flask import Flask, request, jsonify from functools import wraps from ipwhois_guard import check_ip, report_ip app = Flask(__name__) # Track failed logins _login_fails = {} def block_blacklisted(f): @wraps(f) def decorated(*args, **kwargs): ip = request.headers.get("X-Forwarded-For", request.remote_addr) ip = ip.split(",")[0].strip() if check_ip(ip): return jsonify({"error": "Blocked"}), 403 return f(*args, **kwargs) return decorated @app.route("/login", methods=["POST"]) @block_blacklisted def login(): ip = request.remote_addr # On failed login: _login_fails[ip] = _login_fails.get(ip, 0) + 1 if _login_fails[ip] >= 5: report_ip(ip, "brute-force", f"Flask login: {_login_fails[ip]} failed") return jsonify({"error": "Too many attempts"}), 429 return jsonify({"status": "ok"})
Django Middleware
middleware/ipwhois.py
from django.http import JsonResponse from ipwhois_guard import check_ip PROTECTED_PATHS = ["/admin/", "/accounts/login/", "/api/"] class IPWhoisMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): if any(request.path.startswith(p) for p in PROTECTED_PATHS): xff = request.META.get("HTTP_X_FORWARDED_FOR") ip = xff.split(",")[0].strip() if xff else request.META.get("REMOTE_ADDR", "") if check_ip(ip): return JsonResponse({"error": "Blocked"}, status=403) return self.get_response(request)

Add to settings.py:

MIDDLEWARE = [ 'middleware.ipwhois.IPWhoisMiddleware', # ... other middleware ]
FastAPI
main.py
from fastapi import FastAPI, Request, HTTPException from ipwhois_guard import check_ip, report_ip app = FastAPI() @app.middleware("http") async def ipwhois_middleware(request: Request, call_next): ip = request.headers.get("x-forwarded-for", request.client.host) ip = ip.split(",")[0].strip() protected = ["/login", "/admin", "/api"] if any(request.url.path.startswith(p) for p in protected): if check_ip(ip): raise HTTPException(status_code=403, detail="Blocked") return await call_next(request)
Troubleshooting
  • requests not installed: pip install requests
  • SSL errors: pip install --upgrade certifi
  • Behind proxy: Use X-Forwarded-For or X-Real-IP header for real client IP.
  • Async apps: Replace requests with httpx for async support: pip install httpx
  • Memory growth: For production, replace the dict cache with Redis: pip install redis