Every disposable email domain we know of, kept current, and a free API to refuse them at sign-up.
99,139
Check an address
Type an email address or a domain. Try or .
Why block them
A throwaway inbox lives for ten minutes. It lets one person open a hundred accounts, take the free trial again and again, and leave nothing behind to reach.
Refusing these domains at sign-up stops that, and costs real people nothing: nobody keeps their only address at a disposable domain. The list grows every day as new services appear, so a copy you made last year is already behind.
How to use it
- Check at sign-up. Before the account is created, ask the API about the address. One request, a yes or a no, in a few milliseconds.
- Or keep your own copy. Download the list once a day and check against it locally: no request per sign-up, nothing to wait on, nothing that can be down.
- Match the parent too. A subdomain of a listed domain is disposable as well. The API does this for you; the Python example below shows how with a local copy.
- Check on the server. A check that only runs in the browser is skipped by anyone who wants to. Run it where the account is created.
API
Free, no key, no account. JSON over HTTPS, open to any origin (CORS). Base URL https://burnerlist.dev/api/v1
| Method | Path | Returns |
|---|---|---|
| GET | /check?email=address | Whether the address's domain is disposable. ?domain= works the same. |
| GET | /domains.txt | The whole list, one domain per line, sorted. |
| GET | /domains.json | The whole list as a JSON array. |
| GET | /stats | How many domains, and when the list last changed. |
| GET | /recent | The 50 most recent additions, newest first. |
Answers
200 · listed (a subdomain matches its parent) { "domain": "inbox.mailinator.com", "disposable": true, "match": "mailinator.com" } 200 · not listed { "domain": "gmail.com", "disposable": false } 400 · not an address or a domain { "error": "invalid_domain" }
Examples
# Is this address disposable? curl "https://burnerlist.dev/api/v1/check?email=someone@mailinator.com" # {"domain":"mailinator.com","disposable":true,"match":"mailinator.com"}
const API = "https://burnerlist.dev/api/v1"; async function isDisposable(email) { const res = await fetch(`${API}/check?email=${encodeURIComponent(email)}`); if (!res.ok) return false; // never block a sign-up because the check failed const { disposable } = await res.json(); return disposable; } if (await isDisposable(form.email)) { throw new Error("Please use a permanent email address."); }
# Fetch the list only when it changed (ETag), e.g. from cron at 04:00 curl -sf --etag-save list.etag --etag-compare list.etag \ -o disposable.txt https://burnerlist.dev/api/v1/domains.txt
domains = set(open("disposable.txt").read().split()) def is_disposable(email): host = email.rsplit("@", 1)[-1].strip().lower() parts = host.split(".") return any(".".join(parts[i:]) in domains for i in range(len(parts) - 1))
Limits
- Checks120 per minute per IP
- Whole-list downloads30 per hour per IP
- Stats and recent additions240 per minute per IP
Over a limit the API answers 429 with Retry-After. Every answer carries RateLimit-Remaining. The lists come with an ETag: send it back as If-None-Match and an unchanged list costs a 304 and no download. For heavy traffic, keep a copy instead of checking each sign-up.