Disposable Email Domains List & Checker API

A free, public list of 9,967 disposable email domains and a checker API that tells you whether an address belongs to one. No key, no signup. It is published by a temporary-email service — us — and it includes our own domains. That is the point: if your signup form does not want throwaway addresses, we would rather you block us accurately than guess.

# The whole list, one domain per line
curl -s https://temp-mailx.com/api/v1/disposable-domains.txt

# Is this address disposable?
curl -s "https://temp-mailx.com/api/v1/disposable-domains/check?email=someone@0-mail.com"
# -> {"domain":"0-mail.com","disposable":true,"matchedBy":"list","ours":false,"matched":"0-mail.com"}

What the list is and where it comes from

The list has two parts, merged on every request and deduplicated:

  • The public dataset. 9,963 domains from the disposable-email-domains project on GitHub, the community-maintained blocklist most spam filters and signup validators already use. It is released under CC0 (public domain), so you can copy, redistribute and embed it freely. We normalise it (lowercase, trimmed, invalid hostnames dropped) and commit a snapshot into our codebase so the API never depends on GitHub being up.
  • Our own domains. Every domain Temp-MailX currently issues addresses on, plus the ones we have retired, read live from our domain registry. Right now that is 1 live domain (sonabnaglair.top) and 3 retired.

Mainstream mailbox providers — gmail.com, outlook.com, yahoo.com, icloud.com, protonmail.com and the like — are never on the list, even if an upstream contributor adds one by mistake. A blocklist that flags Gmail is wrong for the majority of real users, so the server refuses to report them as disposable regardless of the data file.

Why we publish our own domains in a blocklist

It looks self-defeating. A temporary-email service that hands its own domains to the people blocking temporary email is helping its users get rejected. We do it anyway, for two reasons.

First, honesty is the product. Temp-MailX exists so you can sign up for a newsletter or a one-off download without giving away your real address. It does not exist to help anyone create a thousand fake accounts on a site that has clearly decided it does not want disposable mail. When a site blocks our domains, the person trying to register learns immediately that this service wants a permanent address, instead of waiting for a verification email that silently never arrives. That is a better experience for them and for the site.

Second, a list that hides its publisher is not a list anyone should trust. Every other entry here is somebody else's domain, scraped and reported by volunteers. The one set of domains we can vouch for with certainty is ours — and a list that quietly left those out would be telling you exactly how much to trust the rest. We would rather be blocked honestly than used for abuse.

The flip side: if you run a service and want to allow our addresses — for your own test suites, say — the ours flag in the checker response lets you treat us differently from the rest of the list.

How to use the checker

Three endpoints, all under https://temp-mailx.com/api/v1, all public:

Method & pathReturns
GET /api/v1/disposable-domainsJSON: { count, updatedAt, source, domains: [...] }
GET /api/v1/disposable-domains.txtPlain text, one domain per line (pipe it straight into a file)
GET /api/v1/disposable-domains/check?email=…JSON: { domain, disposable, matchedBy, ours, matched } — ?domain=… also works
POST /api/v1/disposable-domains/checkBody { "emails": [...] }, up to 100; one result per input, in order

matchedBy is "list" for a dataset hit, "ours" for one of our domains, or "none". Subdomains match their parent, so mail.0-mail.com is flagged because 0-mail.com is. A malformed address returns 400; in a batch it comes back with valid: false instead of failing the whole request.

curl

# One address
curl -s "https://temp-mailx.com/api/v1/disposable-domains/check?email=jane@example.com"

# A batch
curl -s -X POST https://temp-mailx.com/api/v1/disposable-domains/check \
  -H "Content-Type: application/json" \
  -d '{"emails":["jane@example.com","bob@0-mail.com","nonsense"]}'

JavaScript (browser or Node 18+)

async function isDisposable(email) {
  const url = new URL('https://temp-mailx.com/api/v1/disposable-domains/check');
  url.searchParams.set('email', email);
  const res = await fetch(url);
  if (res.status === 400) return false;          // not a usable address — let your validator say so
  const { disposable } = await res.json();
  return disposable;
}

// In a signup form:
if (await isDisposable(input.value)) {
  showError('Please use a permanent email address.');
}

The endpoints send Access-Control-Allow-Origin: *, so this works from a page without a proxy.

Python

import requests

API = "https://temp-mailx.com/api/v1/disposable-domains"

def is_disposable(email: str) -> bool:
    r = requests.get(f"{API}/check", params={"email": email}, timeout=5)
    if r.status_code == 400:
        return False
    r.raise_for_status()
    return r.json()["disposable"]

# Or download the list once and match locally — better for bulk work:
domains = set(requests.get(f"{API}.txt", timeout=10).text.split())
def is_disposable_offline(email: str) -> bool:
    host = email.rsplit("@", 1)[-1].lower()
    parts = host.split(".")
    return any(".".join(parts[i:]) in domains for i in range(len(parts) - 1))

Rate limits and caching

Each IP address may make 60 requests per minute across these endpoints. Over that you get 429 with a Retry-After header and the same error envelope as the rest of the API: { "error": "rate_limited", "message": "…" }. That is plenty for a signup form; it is not meant for scanning a database. For bulk work download the list once — it is about 150 KB — and match locally, as in the Python sample above.

Both list endpoints are served with Cache-Control: public, max-age=3600 and an ETag. Send If-None-Match with the ETag you last saw and you will get a 304 with no body when nothing has changed, which saves you the download.

Update cadence

Our own domains change the moment they change: a domain we add goes live in the list on its next request, and a domain we retire stays in it permanently. The public dataset is a committed snapshot that we refresh with deploys, typically a few times a month. The updatedAt field reflects whichever of the two moved most recently. If you find a disposable provider missing, report it upstream to the GitHub project — that way every service using the list benefits, not only ours.

Is gmail.com a disposable email domain?

No. gmail.com is Google's permanent, free mailbox service, used by well over a billion people. A Gmail address is tied to a Google account, persists until its owner deletes it, and is exactly what most sites mean by a “real” email. Our checker returns disposable: false for gmail.com and for googlemail.com, and will keep doing so regardless of what any dataset says.

The confusion usually comes from aliasing. Gmail ignores dots in the local part and anything after a plus sign, so j.ane@gmail.com, jane+shop@gmail.com and jane@gmail.com all land in one inbox. People use those variants to register more than once, and site owners ask whether they can block them. A domain list cannot help: the domain is gmail.com in every case. Our own temp Gmail page issues real Gmail dot-variants for exactly this reason — they pass every disposable-domain filter in existence, including this one. If that matters to you, normalise Gmail addresses before storing them (strip dots and the plus suffix from the local part), rather than hoping a blocklist will catch it.

Frequently asked questions

Do I need an API key?

No. These three endpoints are open. The rest of the Temp Mail API — creating inboxes and reading messages — needs a key.

Can I redistribute the list?

Yes. The upstream dataset is CC0, and our own domains are facts about a public service. Keep the attribution to the GitHub project if you republish it; it is the right thing to do and it is how the list keeps getting better.

Is the list complete?

No list is. New disposable providers appear weekly, and some deliberately rotate domains to stay off lists. Treat a false as “not known to be disposable”, never as proof of a permanent address. For critical flows, pair the check with a real verification email.

Why does a subdomain of a listed domain count?

Because it is the same operator. A provider on example.com that hands out user@mx1.example.com is still the provider. Matching on suffix closes that gap without listing every subdomain by hand.

Can I get the list in another format?

JSON and plain text cover nearly every use. For a hosts file, CSV or a language-specific package, download the text variant and transform it; it is one domain per line, already sorted.

What do you log?

Rate-limit counters keyed on a hash of the caller's IP, kept for one minute. We do not store the addresses you check.

See the API documentation for the inbox endpoints, or the OpenAPI 3.1 spec for the machine-readable contract covering everything on this page.