CheckDisposable Emailcheckdisposable.email
← All guidesFastAPI guide · Python

Block disposable email signups in FastAPI

Use a Pydantic validator or a FastAPI dependency. The async dependency runs concurrently with other dependencies, so latency stays minimal.

The code

# app/auth.py
import os, httpx
from fastapi import HTTPException, Depends
from pydantic import BaseModel, EmailStr

class SignupBody(BaseModel):
    email: EmailStr
    password: str

CDE_URL = "https://api.checkdisposable.email/v1/check"
CDE_KEY = os.environ["CDE_KEY"]

async def reject_disposable(body: SignupBody) -> SignupBody:
    try:
        async with httpx.AsyncClient(timeout=3.0) as client:
            r = await client.get(
                CDE_URL,
                params={"email": body.email},
                headers={"Authorization": f"Bearer {CDE_KEY}"},
            )
            if r.is_success and r.json().get("is_disposable"):
                raise HTTPException(400, "Please use a real email address.")
    except httpx.HTTPError:
        pass  # fail open
    return body

# main.py
from fastapi import FastAPI
app = FastAPI()

@app.post("/signup")
async def signup(body: SignupBody = Depends(reject_disposable)):
    # ...create user
    return {"ok": True}

Notes

Why a Depends, not a validator
Pydantic validators run synchronously. The disposable check is I/O — async. Using a FastAPI dependency means the call is properly awaited without blocking the event loop.
Type-safe + reusable
The `reject_disposable` dependency returns the typed body, so any handler can drop it in via `Depends()` and still benefit from full Pydantic typing.
Tie to email-only routes
For OAuth callback routes, factor `is_disposable(email)` out as a plain async function and call it inside the OAuth flow instead of using `Depends`.

Get a free API key

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

Sign up free →