CheckDisposable Emailcheckdisposable.email
← All guidesFlask guide · Python

Block disposable email signups in Flask

Add a decorator that runs before your signup view. Works with Flask-Login, Flask-Security, or vanilla Flask.

The code

# app/auth.py
import os, functools, requests
from flask import request, jsonify, abort

CDE_KEY = os.environ["CDE_KEY"]

def is_disposable(email: str) -> bool:
    try:
        r = requests.get(
            "https://api.checkdisposable.email/v1/check",
            params={"email": email},
            headers={"Authorization": f"Bearer {CDE_KEY}"},
            timeout=3,
        )
        return r.ok and r.json().get("is_disposable") is True
    except requests.RequestException:
        return False  # fail open

def block_disposable(view):
    @functools.wraps(view)
    def wrapped(*args, **kwargs):
        email = (request.get_json(silent=True) or {}).get("email") or request.form.get("email")
        if email and is_disposable(email):
            return jsonify(error="Please use a real email address."), 400
        return view(*args, **kwargs)
    return wrapped

# routes.py
from flask import Blueprint
auth_bp = Blueprint("auth", __name__)

@auth_bp.post("/signup")
@block_disposable
def signup():
    # ...create user
    return jsonify(ok=True)

Notes

Decorator order
Apply `@block_disposable` ABOVE any login decorators so anonymous signups still get the check.
JSON or form
The decorator reads from both `request.json` and `request.form`, so it works for SPA POSTs and traditional HTML form submissions.
Async option
On Flask 2+ with the `async` extra, swap `requests` for `httpx.AsyncClient` to avoid blocking the event loop on `gunicorn --worker-class uvicorn.workers.UvicornWorker`.

Get a free API key

500 checks/month, no credit card. No credit card. 30 seconds.

Sign up free →