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
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-FororX-Real-IPheader for real client IP. - Async apps: Replace
requestswithhttpxfor async support:pip install httpx - Memory growth: For production, replace the dict cache with Redis:
pip install redis