MoeMail

Disposable Email Checker

Enter a domain and find out whether it belongs to a disposable email provider. Free, no signup — and yes, we mark our own domains too.

You can paste a full address (name@example.com) — only the domain is used, and nothing is stored.

20 common domains, already checked

These verdicts are generated from the same data the checker uses, so they can never drift out of sync with it. The description explains what each service is; the verdict reflects what the blocklists say about it.

DomainVerdictWhat it is
gmail.comNot listed as disposableGoogle's consumer mail service.
outlook.comNot listed as disposableMicrosoft's consumer mail service.
yahoo.comNot listed as disposableYahoo Mail.
icloud.comNot listed as disposableApple's mail service, tied to an Apple account.
proton.meNot listed as disposablePrivacy-focused provider with free and paid plans.
qq.comNot listed as disposableTencent QQ Mail, one of the most used providers in China.
163.comNot listed as disposableNetEase Mail, widely used in China.
gmx.comNot listed as disposableGMX, a long-running free provider.
zoho.comNot listed as disposableZoho Mail, aimed at businesses and custom domains.
simplelogin.ioNot listed as disposableAlias service that forwards to your real inbox.
duck.comNot listed as disposableDuckDuckGo Email Protection, an alias-forwarding service.
mailinator.comListed as disposablePublic throwaway inboxes that anyone can open without signing up.
yopmail.comListed as disposableThrowaway inbox provider.
guerrillamail.comListed as disposableThrowaway inbox provider, one of the oldest still running.
sharklasers.comListed as disposableOne of Guerrilla Mail's alternative domains.
10minutemail.comListed as disposableThrowaway inbox that expires after a short window.
temp-mail.orgListed as disposableThrowaway inbox provider with many regional domains.
1secmail.comListed as disposableThrowaway inbox provider that also offers a public API.
trashmail.comListed as disposableForwarding-based throwaway addresses with expiry.
moemail.appThis is one of oursThis service. A disposable email provider — see the section below.

Why there are two levels instead of yes or no

Most free checkers answer with a flat true or false. That hides the thing you actually need to know: how sure the answer is. We use two lists with different editorial standards, and tell you which one matched.

Listed

The domain is in a conservatively curated blocklist — entries are reviewed, and false positives are rare. If you are going to block or flag an address automatically, this is the level to act on.

Possibly

The domain is only in the broader list, which favours coverage over precision. Useful as one signal among several. Blocking on this level alone will occasionally reject a legitimate user.

Not listed

Neither list has it. Note what this does and does not mean: no blocklist is ever complete, and a brand-new disposable domain will pass this check for a while.

A blocklist match is evidence, not proof. For anything consequential, combine it with signals you control — MX records, domain age, account behaviour, or a confirmation email.

Alias services are not the same as disposable email

Services like SimpleLogin, DuckDuckGo Email Protection, and Gmail's own plus-addressing give you an address that forwards to a mailbox you keep. The address is disposable; the mailbox behind it is not. The person still reads their mail, still replies, and still recovers their account later.

Blocklists disagree about how to treat them, so you may see an alias domain flagged. That is worth knowing before you block one: rejecting alias users turns away privacy-conscious people who are otherwise perfectly real customers. A disposable inbox is abandoned in minutes; an alias can outlive the account it was created for.

The data contradicts itself in ways worth seeing. addy.io is listed, while anonaddy.com — the same company's older domain — is not. relay.firefox.com is listed even though Firefox Relay actually hands out addresses on mozmail.com, which is not listed at all. Both of those flags land in the 'possibly' tier rather than 'listed', which is precisely what that tier exists for.

We list our own domains as disposable

MoeMail is a disposable email service. Our domains do exactly what the blocklists describe, so the honest answer is that they belong on those lists — and this checker says so.

We could have quietly excluded ourselves. We did not, for a plain reason: anyone can test their own domain against a checker in five seconds, and a tool caught hiding its owner is worth nothing. If you run a site and want to keep throwaway signups out, you should be able to use this tool to block us too.

How sites actually detect disposable email

A blocklist lookup like this one is only the first layer. Real systems stack several checks: matching the domain against public and commercial lists, resolving MX records to see whether mail is even accepted, looking at how recently the domain was registered, and watching what the account does after signup.

That is also why an address sometimes gets rejected even though it is not on any list — and why a disposable address occasionally sails through. If you want the longer version, we wrote about it separately.

Why websites block disposable email

Where the data comes from

The checker queries two open blocklists maintained by the community. The second is an aggregator, so the repositories feeding it are credited below as well — every one of them linked back to its source. We rebuild our copy from upstream rather than editing entries by hand, so what you get here matches what the maintainers publish.

This is not an exhaustive account of the data. The aggregator also scrapes throwaway-mail websites, which have no repository or licence to name. Its source is published, so you can audit the full set yourself: generator.py

Download the list

The merged, deduplicated list is available as a plain text file — one domain per line, no key, no rate limit. Use it in your own project.

disposable-domains.txt

Neither list claims to be current or complete, and the maintainers say so plainly. Domains change hands, services shut down, and new ones appear every day. Treat what you get here as a community-maintained snapshot rather than a live authority.

Free disposable email API

The same lookup this page runs, as a JSON endpoint. No API key, no sign-up, no quota to top up — call it from a signup form, a Worker, or a shell script. It reads the same two lists documented above, so the answer it returns is the answer you see here.

Try it
curl "https://moemail.app/api/tools/v1/disposable-email/check?domain=mailinator.com"

Endpoints

GEThttps://moemail.app/api/tools/v1/disposable-email/check?domain=…

Check one domain, or a full email address — the local part is dropped. Returns a verdict for the normalised domain.

GEThttps://moemail.app/api/tools/v1/disposable-email/dataset

Which snapshot of the lists is answering: tier sizes, build timestamp, and the SHA-256 of each upstream file as it was downloaded. Call it once at start-up if you want to record which data produced a decision.

Response fields

domainstring
The normalised domain the verdict applies to: lowercased, local part and trailing dots removed. Compare against this rather than against what you sent.
disposableboolean
True when the domain appears in either list, including our own. This is the coarse answer — read the warning below before you gate a signup on it.
verdict"high" | "medium" | "none" | "ours"
Which tier matched. high is the conservatively curated list. medium is the broad aggregator list only. none is in neither. ours is one of MoeMail's own receiving domains, which are disposable and which no third-party list knows about.

Do not block on disposable alone

medium is roughly 66,000 of the 75,000 domains we know about, and it comes from a broad aggregator that nobody curates by hand. Blocking every one of them will reject real users. If a false positive costs you a customer, gate on verdict === "high" and treat medium as a reason to ask for a second factor, not a reason to refuse. disposable exists so that a drop-in replacement for a boolean API keeps working — not because a boolean is the right decision boundary.

Errors

Every error carries a machine-readable code alongside the human-readable error. Branch on code: the prose may be reworded at any time, the codes will not change without a new API version.

400missing_domainNo domain parameter was given, or it was empty.
400invalid_domainNot a plausible domain. Also returned when domain was repeated, and for Unicode domains — encode those as punycode (xn--…) first.
400input_too_longThe parameter exceeded 320 characters, which is the longest a real address can be.

Limits, caching and stability

17 requests per 10 seconds per IP address, enforced at Cloudflare's edge rather than inside this API. There is no key that raises it and no paid tier — if you need more than that, download the full list and look domains up locally instead.

Exceed it and Cloudflare blocks the request at its edge, before it reaches this API: 429, Retry-After: 10, and a short text/plain body — not the JSON shape above. Two consequences worth planning for. The block carries no Access-Control-Allow-Origin, so a browser sees an opaque network error rather than a readable 429; and since the request never arrives here, there is no code field to branch on. Treat a request that fails immediately after a burst as rate limiting.

Responses are cacheable for a day (s-maxage=86400) and carry an ETag derived from the upstream file hashes, so a conditional request costs nothing while the data is unchanged. The lists are compiled at build time, so an answer cannot change until the next deploy. One consequence worth knowing: a cached response never reaches the rate limiter, so the limit shapes traffic rather than guaranteeing it.

Every response sends Access-Control-Allow-Origin: *, so a browser can call this straight from your signup form with no proxy in between.

v1 is a promise about shape, not about data: fields will not be removed or renamed, and status codes will not change meaning, without a new version segment in the path. The verdicts themselves change whenever the upstream lists do.

Code examples

Each one gates on verdict rather than on the boolean, because that is the decision you actually want to make.

cURL
curl "https://moemail.app/api/tools/v1/disposable-email/check?domain=mailinator.com"
# {"domain":"mailinator.com","disposable":true,"verdict":"high"}

curl "https://moemail.app/api/tools/v1/disposable-email/dataset"
# {"high":8742,"medium":66885,"total":75627,"builtAt":"…","status":"upstream",…}
Node.js
const ENDPOINT = "https://moemail.app/api/tools/v1/disposable-email/check"

async function verdictFor(domain) {
  const res = await fetch(`${ENDPOINT}?domain=${encodeURIComponent(domain)}`)
  const body = await res.json()
  if (!res.ok) throw new Error(body.code)   // branch on `code`, never on `error`
  return body.verdict
}

// "medium" means "only in the broad aggregator list" — a signal, not a verdict.
// Gate signups on the tier you are willing to defend to a real user.
const verdict = await verdictFor("mailinator.com")
const reject = verdict === "high" || verdict === "ours"
Python
import requests

ENDPOINT = "https://moemail.app/api/tools/v1/disposable-email/check"

def verdict_for(domain: str) -> str:
    r = requests.get(ENDPOINT, params={"domain": domain}, timeout=5)
    r.raise_for_status()
    return r.json()["verdict"]

# Note: use requests (or set an explicit User-Agent). Cloudflare's managed bot
# rules block the default "Python-urllib/3.x" agent with a 403 before the
# request ever reaches this API.

if verdict_for("mailinator.com") in ("high", "ours"):
    ...  # reject the signup
PHP
<?php
function verdict_for(string $domain): string {
    $url = 'https://moemail.app/api/tools/v1/disposable-email/check?domain=' . urlencode($domain);
    $ctx = stream_context_create(['http' => [
        'timeout' => 5,
        // Send a real User-Agent: identify your app, and stay clear of any
        // bot rule that keys on a default library agent.
        'header'  => "User-Agent: my-app/1.0\r\n",
    ]]);
    $body = json_decode(file_get_contents($url, false, $ctx), true);
    return $body['verdict'];
}

if (in_array(verdict_for('mailinator.com'), ['high', 'ours'], true)) {
    // reject the signup
}
Cloudflare Worker
export default {
  async fetch(request) {
    const email = new URL(request.url).searchParams.get("email") ?? ""
    const domain = email.split("@").pop()

    // Responses are cacheable (s-maxage=86400), so the Cache API turns a
    // repeated lookup into zero subrequests.
    const res = await fetch(
      `https://moemail.app/api/tools/v1/disposable-email/check?domain=${encodeURIComponent(domain)}`,
      { cf: { cacheTtl: 86400, cacheEverything: true } },
    )
    const { verdict } = await res.json()

    return Response.json({ allow: verdict !== "high" && verdict !== "ours" })
  },
}

The lists are compiled from public upstream sources, some under licences that require their notices to travel with the data. Every response carries a Link: rel="license" header pointing back to the attributions above, and the full notices ship in the header of the downloadable dataset.

How this compares to other free lookup APIs

There are a handful of free disposable-domain lookups that need no key. Here is where this one differs — and where it does less.

FeatureMoeMailKickbox OpenDeBounce Freevalidator.pizza
No API key or sign-upYesYesYesYes
Callable from a browser (CORS)YesNoYesYes
Confidence detailTwo tiers, plus its own domainsOne booleanOne boolean, sent as a stringOne boolean
Names its sources, with checksumsYesNoNoNo
Full list downloadableYesNoNoNo
Data version is queryableYesNoNoNo
Live MX / domain-age lookupNoNoNoYes
Stated rate limit17 per 10s, documentedNot statedNot statedx-ratelimit-limit: 1

Every cell was verified by calling the endpoint on 2026-08-22, with requests of the same shape as the cURL example above — so you can re-run them yourself. Nothing here comes from a vendor's marketing page: one search result claimed the Kickbox endpoint supports CORS, and it does not.

All four are blocklist lookups. They answer "is this domain known to be disposable" and nothing more; none of them, this one included, can tell you whether a mailbox actually exists. validator.pizza goes furthest, resolving MX records and domain age live — if that is what you need, use it.

Paid validation services — ZeroBounce, Kickbox's own verification API, Bouncer — do considerably more than any of this, including mailbox existence and catch-all detection, and charge per check. They are not in the table because measuring them against dimensions chosen by a free blocklist would be a rigged comparison.

Questions

No. Gmail is Google's consumer mail service and does not appear in disposable blocklists. Addresses on it belong to accounts that persist, so they are not throwaway addresses. Gmail's plus-addressing (name+tag@gmail.com) creates a disposable-looking variant, but the mail still lands in the same permanent inbox.

No. The lookup happens against a list compiled into the site at build time, and the domain you enter is not written to any log or database of ours.

Yes. Paste the whole address and only the part after the @ is used. The local part is discarded immediately and never leaves the request.

Blocklists lag reality. New disposable domains launch constantly and take time to be reported and reviewed. A not-listed result means no list has it yet — not that the domain is trustworthy.

Block on the 'listed' level if you want throwaway signups gone. Be more careful with 'possibly' — that list trades precision for coverage, and blocking on it alone will occasionally turn away a real customer. Alias-forwarding services deserve particular care.

We rebuild it from upstream periodically. Because it ships with the site rather than being fetched at request time, the list you are querying is the one from our most recent deploy.

Yes — a free JSON endpoint with no key and no sign-up: GET /api/tools/v1/disposable-email/check?domain=example.com. It is limited to 17 requests per 10 seconds per IP address and sends Access-Control-Allow-Origin: *, so you can call it straight from a browser. The full reference, plus examples for Node, Python, PHP and Cloudflare Workers, is in the API section above.

It stays free, because it costs us almost nothing: the lists are compiled at build time and the responses are cached at the edge for a day, so most calls never reach a server at all. There is no key to buy and no higher tier. If you need more throughput than the limit allows, download the full list and look domains up locally — that is what it is published for, and a local lookup is faster than any network call could be.

Need a disposable address yourself?

MoeMail creates temporary mailboxes that expire on your schedule — 10 minutes to 3 days — and deletes the mail with them.