Skip to content

Disposable email checker APIs: open lists vs paid services

· Updated · 7 min read · Disposable email

For most signup forms, an open blocklist checked in your own process is the right disposable email checker: it costs nothing, adds no latency and never sends your users' addresses to a third party. Paid services are worth it when you also need deliverability data (does the mailbox exist, is the domain catch-all) or fraud scoring, and the disposable flag comes bundled with that. Free hosted endpoints sit in between: fine for prototypes and low volume, risky as a hard dependency in your signup path.

That's the short answer. The rest of this post covers the four kinds of options, how they fail, and a layered setup you can copy.

The four kinds of disposable email checker

Option Examples Cost Latency What you get back Main risk
Open list in your process disposable-email-domains, wesbos/burner-email-providers Free Microseconds Your own boolean Goes stale unless you refresh it
Free hosted endpoint Kickbox open API, DeBounce free API Free, no key One network round trip A single boolean No SLA, undisclosed rate limits
Paid verification API ZeroBounce, Abstract Per credit or monthly plan Hundreds of ms to seconds Disposable plus deliverability status Cost per signup, full address leaves your system
Domain intelligence / risk API pingutil, fraud-scoring vendors Free to enterprise Milliseconds to seconds Category, signals, a verdict Another dependency to monitor

The categories overlap. A verification API checks a disposable list internally, and a domain intelligence API usually syncs from the same open lists you could download yourself. What you're choosing is mostly who maintains the list, what else comes in the response, and what happens when the call fails.

Open lists disagree more than you'd expect

The two best-known open lists are disposable-email-domains (CC0 licensed) and wesbos/burner-email-providers (MIT licensed). We downloaded both on 12 October 2026 and compared them:

  • disposable-email-domains: 9,880 entries
  • burner-email-providers: 27,277 entries
  • In both: 3,987

So more than half of the smaller list is missing from the bigger one. Bigger is not automatically better either. The burner list contains duck.com, which is DuckDuckGo's email forwarding service, and sohu.com, a large Chinese web portal with a webmail product. Block on that list and you turn away privacy-conscious real users. Forwarding services are a separate problem from throwaway inboxes, covered in why Apple Hide My Email and Firefox Relay are not disposable email.

You can reproduce the comparison in a few lines:

curl -s https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/main/disposable_email_blocklist.conf \
  | tr 'A-Z' 'a-z' | sort -u > a.txt
curl -s https://raw.githubusercontent.com/wesbos/burner-email-providers/master/emails.txt \
  | grep -v '^#' | tr 'A-Z' 'a-z' | sort -u > b.txt

comm -12 a.txt b.txt | wc -l   # in both lists
comm -23 a.txt b.txt | wc -l   # only in disposable-email-domains
comm -13 a.txt b.txt | wc -l   # only in burner-email-providers

Run the last command and skim the output before you adopt any list for hard blocking. You'll learn more about its quality in five minutes than from any README.

What we look for in a list is the review process, not the size. disposable-email-domains asks contributors to attach a screenshot of a page that hands out addresses on the domain, and accepts removal requests. Its README is also honest about the limits: "We cannot guarantee all of these can still be considered disposable." Treat that sentence as a design constraint. Any list will have false positives, so your product needs a way for a wrongly blocked user to get through. Why lists rot and how to keep yours current is its own topic: see why disposable email blocklists go stale.

Free hosted endpoints: read the fine print

Two free endpoints answered without an API key when we tested them today:

curl -s https://open.kickbox.com/v1/disposable/mailinator.com
# {"disposable":true}

curl -s "https://disposable.debounce.io/?email=test@mailinator.com"
# {"disposable":"true"}

Look closely at the second response. The value is the string "true", not a boolean, and the DeBounce docs show it that way. A naive if (data.disposable) in JavaScript treats "false" as truthy and blocks every signup. Compare against the string, or normalise it.

Both are good for prototypes and internal tools. Before you put either in a production signup path, note what the providers themselves say. DeBounce states that "the exact rate limit is not publicly disclosed". Kickbox's open page says the software is provided "as is" and "as and when available", without warranty. Neither promises an SLA, which is fair for a free service. It just means you must fail open when they time out.

Paid email verification services bundle the disposable check with everything else they do: syntax, MX, mailbox probing, catch-all detection. Two examples, with pricing as shown on their official pages on 12 October 2026:

  • ZeroBounce reports disposable addresses as status do_not_mail with sub-status disposable. Its pricing page lists 100 free validation credits a month (when you sign up with a business domain) and pay-as-you-go from $39 for 2,000 validations, roughly two cents per check at that tier.
  • Abstract's email validation API flags disposable and catch-all addresses. It lists a free plan with 100 requests and a Starter plan for 5,000 requests a month. The page shows $17 in the plan cards and $19 for monthly billing in its FAQ, so confirm before you budget.

If you send email to your users and bounces hurt your sender reputation, this category earns its price. If you only want to stop throwaway inboxes at signup, you're paying for a lot you won't use. Be skeptical of mailbox-level results too: SMTP mailbox probing is unreliable for reasons no vendor can fully fix, since many servers accept every address or block probes.

Questions to ask before you pick one

  1. What happens when it's down? Your signup flow should fail open (accept the user, flag for later review) on timeout or 5xx. If a vendor outage can stop all signups, that's your bug, not theirs.
  2. Do you send the full address or only the domain? Disposable detection only needs the domain. Kickbox and DeBounce both accept a bare domain. Sending full addresses means a third party is processing your users' personal data, which your privacy policy should cover.
  3. Who decides what gets added, and how fast? A list with a review process and weekly updates beats a giant list with no provenance.
  4. Does it separate forwarding services from throwaway inboxes? Relay addresses belong to real, often valuable, users.
  5. Do you get a reason or just a boolean? A reason lets you show a useful error message, log why you rejected someone and tune your policy later.
  6. What's your latency budget? A signup form can afford 200 ms. A form that validates on every keystroke cannot, so check locally first.

A layered setup that costs nothing

The pattern we recommend: keep a local copy of an open list for instant hits, then ask a remote API for everything else, with a short timeout and a fail-open path. The remote call catches domains added upstream since your last deploy, plus things a domain list can't see, like machine-generated local parts.

import { readFileSync } from 'node:fs';

// Refresh this file on a schedule (weekly is fine), not only at build time.
const DISPOSABLE = new Set(
  readFileSync('./disposable_email_blocklist.conf', 'utf8')
    .split('\n')
    .map((line) => line.trim().toLowerCase())
    .filter(Boolean),
);

// The list contains entries under shared suffixes (for example x.dynv6.net),
// so check the full host and each parent, not only the registrable domain.
function hostAndParents(host: string): string[] {
  const parts = host.split('.');
  return parts.slice(0, -1).map((_, i) => parts.slice(i).join('.'));
}

type DisposableCheck = {
  disposable: boolean;
  source: 'local' | 'remote' | 'unavailable';
};

export async function checkDisposable(email: string): Promise<DisposableCheck> {
  const host = email.split('@').pop()!.trim().toLowerCase();
  if (hostAndParents(host).some((h) => DISPOSABLE.has(h))) {
    return { disposable: true, source: 'local' };
  }

  try {
    const res = await fetch('https://pingutil.com/v1/lookup', {
      method: 'POST',
      headers: {
        authorization: `Bearer ${process.env.PINGUTIL_KEY}`,
        'content-type': 'application/json',
      },
      // skip_enrichment: no LLM call, just category + email_signals + verdict
      body: JSON.stringify({ input: email, skip_enrichment: true }),
      signal: AbortSignal.timeout(1500),
    });
    if (!res.ok) return { disposable: false, source: 'unavailable' };
    const data = await res.json();
    return { disposable: data.category === 'disposable', source: 'remote' };
  } catch {
    // Timeout or network error: let the user in, review later.
    return { disposable: false, source: 'unavailable' };
  }
}

A few notes on the pingutil half, since it's our API. It syncs from disposable-email-domains every Monday at 06:00 UTC, so it won't catch a domain the list hasn't added yet. The response also carries verdict.is_spam and verdict.reason, which flag randomized local parts like ccjxx90sze@ on otherwise normal domains; see detecting machine-generated email addresses for how that heuristic works and where it misfires. Each key is limited to 60 requests per minute, so if your signup rate can exceed one per second at peak, cache results per domain for a day. The full request and response shape is in the API reference.

Whatever you call, decide up front what a positive result means. Rejecting the signup, requiring extra verification and quietly limiting the account are all valid, and the right one depends on what a fake account costs you. We cover that decision in should you block disposable emails or just flag them.

A short checklist

  • Start with a local open list. Refresh it weekly from a scheduled job.
  • Diff any list against a second one before you hard-block on it.
  • Send the domain, not the full address, unless you need per-address signals.
  • Put a timeout under 2 seconds on any remote check and fail open.
  • Store the reason and source with each decision so you can audit false positives.
  • Pay for a verification service only if deliverability, not just signup quality, is the problem.

You can browse the domains pingutil currently treats as throwaway on the disposable domains page.

Questions people ask

Is there a free disposable email checker API?
Yes. Kickbox runs a free endpoint at open.kickbox.com and DeBounce runs one at disposable.debounce.io, neither needs a key. pingutil also has a free tier with a 60 requests per minute limit per key. For production, pair any of them with a local copy of an open blocklist so an outage does not block signups.
How often should a disposable domain list be updated?
Weekly is a sensible default. New throwaway domains appear constantly: the disposable-email-domains repository on GitHub had 37 commits in the month before this post. A list baked into your build and never refreshed will miss new domains within weeks.
Should I check for disposable emails in the browser or on the server?
Do the authoritative check on the server. A client-side check is fine for instant feedback, but anyone can skip it by calling your signup endpoint directly.