One endpoint. Bearer auth. JSON in, JSON out.
Base URL
https://api.checkdisposable.emailAuthentication
Pass your API key as a Bearer token. Get one for free at app.checkdisposable.email.
Authorization: Bearer cde_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAnonymous use is also fine for low volume — the same endpoint will rate-limit by IP to 30/hour without a key. That's what powers the checker on the homepage.
Check a single email
GET /v1/check
curl 'https://api.checkdisposable.email/v1/check?email=test@mailinator.com' \
-H 'Authorization: Bearer cde_live_...'Response (200):
{
"email": "test@mailinator.com",
"domain": "mailinator.com",
"is_disposable": true,
"blocked": true,
"reason": "Domain is a known disposable / temporary email provider.",
"duration_ms": 47
}Clean email response:
{
"email": "founder@stripe.com",
"domain": "stripe.com",
"is_disposable": false,
"blocked": false,
"reason": "Domain is not flagged as disposable.",
"duration_ms": 19
}Rate limits
Two limits apply to every API key, both enforced server-side:
| Plan | Monthly cap | Burst |
|---|---|---|
| free | 500 / month | 5 req / sec |
| unlimited | ∞ | 15 req / sec |
| lifetime | ∞ | 15 req / sec |
Headers on every response:
X-RateLimit-Plan: free | unlimited | lifetime
X-RateLimit-Limit: 500 | unlimited
X-RateLimit-Remaining: <int> | unlimited
X-RateLimit-Burst-Limit: 5 | 15
X-RateLimit-Burst-Remaining: <int>When a burst limit is hit, you get 429 rate_limit_exceeded plus a Retry-After header. When the monthly cap is hit, you get 429 plan_limit.
Error codes
| Status | Error | Meaning |
|---|---|---|
| 400 | bad_request | Missing/malformed email parameter. |
| 401 | invalid_api_key | API key is wrong or revoked. |
| 429 | rate_limited / plan_limit | Anonymous IP limit hit, or monthly plan exhausted. |
| 502 | upstream_error | Blocklist provider is temporarily unreachable. Retry. |
Recipes
Node.js
const res = await fetch(
'https://api.checkdisposable.email/v1/check?email=' + encodeURIComponent(email),
{ headers: { Authorization: 'Bearer ' + process.env.CDE_KEY } }
);
const { is_disposable } = await res.json();
if (is_disposable) throw new Error('Disposable signup rejected');Python
import os, httpx
def is_disposable(email: str) -> bool:
r = httpx.get(
"https://api.checkdisposable.email/v1/check",
params={"email": email},
headers={"Authorization": f"Bearer {os.environ['CDE_KEY']}"},
timeout=5.0,
)
r.raise_for_status()
return r.json()["is_disposable"]