Developer Tools
How to Block Disposable Emails at Sign-Up: Free Lists, APIs and a Next.js Example
Block throwaway emails at sign-up: three free open-source domain lists, check APIs with free tiers, built-in auth options and a short Next.js server check.

To block disposable emails at sign-up, check the address's domain on the server against a blocklist before you create the account. A free, CC0-licensed list such as disposable-email-domains covers the common throwaway services. Add a check API if you want to catch new domains faster or spot forwarding services. If you use Clerk, it is a toggle; Supabase and Auth.js give you a hook to run the check yourself.
Below are three open-source lists, three check APIs, what the auth providers offer, and a Next.js example you can copy. Licenses, limits and plan details were checked against each project's or vendor's own page on 11 November 2026.
Why block them at all
If each account gets free credits, a trial or a free tier, throwaway addresses let one person sign up again and again. For AI products every free account costs real inference money. A domain check is nearly free and stops the laziest abuse; it won't stop someone with a stack of Gmail accounts.
Free open-source domain lists
disposable-email-domains
disposable-email-domains
is one plain-text file, disposable_email_blocklist.conf, with one domain per line: 10,181
entries when we downloaded it. It is licensed CC0 (public domain), so you can ship it in a
commercial product without attribution. The README says PyPI uses it to block throwaway
sign-ups, and it is also published as a PyPI package.
Updates are pull-request driven, with no fixed schedule. Contributors must show a page
that hands out addresses on the domain, and a GitHub workflow pulls in domains from
sources. There were 45 commits in the 30 days before we checked. Entries are second-level
domains, so the README tells you to match parent domains too: a.b.example.com should
match example.com. The example below does that.
disposable (disposable/disposable)
disposable is an auto-generated list that the
README says is updated every 24 hours, under the MIT license. The main domains.txt had
102,779 lines when we fetched it, about ten times the list above. It also has extra files
that matter for the trade-offs below:
domains_strict.txtadds providers that allow anonymous sign-up, which the published lists say include outlook.com and hotmail.com. Too aggressive for most sign-up forms.domains_forwarding.txtadds alias and forwarding services such as Apple Hide My Email, Firefox Relay and SimpleLogin, but no freemail providers.
FakeFilter
FakeFilter (BSD-3-Clause) monitors known temp-mail
providers and publishes their domains daily; commits land every night just after midnight
UTC. The text file had about 10,800 lines. Domains drop off after a year of inactivity, and
major mail providers are allowlisted. It ships as TXT, JSON and an npm package
(fakefilter) that bundles the data, so keep the package updated.
Check APIs with a free tier
An API catches domains newer than your list and can return more than yes or no. The cost is a network call during sign-up and sending data to a third party.
UserCheck
UserCheck has a free plan of 1,000 credits a month at one
request per second, with no credit card. The
domain endpoint,
GET https://api.usercheck.com/domain/{domain}, returns disposable, relay_domain,
public_domain and other fields, and sends 429 when you go over the rate limit. There is
also an /email/{email} endpoint. The Pro price is not shown in the page text.
Abstract API
Abstract's Email Validation API has a free plan of 100 requests at 3 requests per second, no card, and also checks MX, SMTP and typos. Paid plans start at $17 a month for 5,000 requests, but the pricing table puts the disposable flag ("email quality") in Professional, not Starter.
Kickbox's free disposable checker
Kickbox runs a free disposable email checker page. A
GET https://open.kickbox.com/v1/disposable/mailinator.com call returned
{"disposable":true} when we tried it (and false for gmail.com), but the page no longer
documents the API (its "Using the API" link is commented out), so use it for manual lookups,
not in production.
Built into your auth provider
- Clerk. Block disposable email addresses is included on every plan and off by default. It checks the domain and its parent domains, at sign-up and when a user adds an email, but not at sign-in. A separate "block risky email domains" protection needs the Business plan.
- Supabase. No built-in list, but the Before User Created hook (a Postgres function or HTTP endpoint) can reject a sign-up, and its docs name disposable domains as a use case. The hooks page lists it on Free and Pro.
- Auth.js. The
signIncallback stops the flow when it returnsfalse. With the email provider, it is called withemail.verificationRequestset totruewhen someone asks for a magic link, which is where you put the domain check.
Side by side
| Option | Type | License or price | Updates | Size or limit | Flags relays |
|---|---|---|---|---|---|
| disposable-email-domains | List | CC0 | PR-driven, no schedule | 10,181 domains | No |
| disposable/disposable | List | MIT | Every 24 hours | 102,779 domains | Separate file |
| FakeFilter | List + npm | BSD-3-Clause | Daily | ~10,800 domains | No |
| UserCheck | API | Free: 1,000 credits/mo | Continuous | 1 request/sec free | relay_domain |
| Abstract API | API | Free: 100 requests | Not published | 3 requests/sec | Not documented |
| Clerk | Auth setting | Every plan | Not published | — | Not documented |
A Next.js server-side check
The check has to run on the server. A client-side check is a hint for the user, nothing more, because anyone can call your sign-up endpoint directly. Start by turning the CC0 list into a JSON array your code can import:
curl -s https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/main/disposable_email_blocklist.conf \
| jq -R -s 'split("\n") | map(select(length > 0))' > lib/disposable-domains.json
Commit the file and refresh it on a schedule, for example a weekly CI job. Then a small helper that matches the domain and its parent domains, as the list's README describes:
// lib/disposable-email.ts
import domains from './disposable-domains.json'
const BLOCKLIST: ReadonlySet<string> = new Set(domains)
export function isDisposableEmail(email: string): boolean {
const at = email.lastIndexOf('@')
if (at === -1) return false
const parts = email.slice(at + 1).trim().toLowerCase().split('.')
for (let i = 0; i < parts.length - 1; i++) {
if (BLOCKLIST.has(parts.slice(i).join('.'))) return true
}
return false
}
And the Server Action that the sign-up form posts to:
// app/sign-up/actions.ts
'use server'
import { isDisposableEmail } from '@/lib/disposable-email'
type SignUpState = { error: string | null }
export async function signUp(
_prev: SignUpState,
formData: FormData,
): Promise<SignUpState> {
const email = formData.get('email')
if (typeof email !== 'string' || !email.includes('@')) {
return { error: 'Enter a valid email address.' }
}
if (isDisposableEmail(email)) {
return { error: 'Please use a permanent email address.' }
}
// create the user, send the verification email...
return { error: null }
}
If you add an API on top, call it only when the local list passes, send just the domain
(UserCheck's /domain/ endpoint needs nothing more), and let the sign-up through if the API
times out or returns 429.
The trade-offs
False positives. No list is perfect. The disposable-email-domains README says it can't guarantee that every entry is still disposable. A wrongly listed domain means a real customer gets turned away, and they rarely tell you. Keep a small allowlist of your own that overrides the blocklist, log every block, and look at the log now and then.
Privacy relays are not throwaway mail. Apple Hide My Email
(privaterelay.appleid.com), Firefox Relay (mozmail.com), DuckDuckGo (duck.com) and
SimpleLogin forward to a real inbox the person keeps. None of them are in the three lists'
main files; they appear only in disposable's forwarding list. Blocking them turns away
people who chose privacy on purpose, so do it only with a concrete reason.
How to choose
- Want zero dependencies and no licensing questions: disposable-email-domains (CC0), bundled as above.
- Want daily updates without running anything: disposable/disposable or FakeFilter, fetched in CI.
- Need to know about forwarding services as well: UserCheck's
relay_domainfield or disposable's forwarding list, and decide case by case. - Already on Clerk: turn on the built-in protection and skip the rest.
- On Supabase or Auth.js: run the same domain check in the Before User Created hook or the
signIncallback.
FAQ
Is there a free list of disposable email domains?
Yes. disposable-email-domains is CC0 and about 10,000 domains, disposable/disposable is MIT and regenerated every 24 hours, and FakeFilter is BSD-3-Clause and updated daily. All three are free to use in commercial products under their licenses.
Is there a free API to detect temporary email addresses?
UserCheck's free plan gives 1,000 credits a month with no card, and Abstract API's free plan gives 100 requests. Kickbox's free checker page works, but its API is no longer documented.
Should I block Apple Hide My Email and other relays?
Usually not. They forward to a real, long-lived inbox, and the person behind them is often a careful user rather than an abuser.
Does blocking disposable emails stop all fake sign-ups?
No. It stops the cheapest kind. Combine it with email verification, rate limits on the sign-up endpoint and limits on what one account gets for free.
Picking a starter that already wires up auth? See Next.js SaaS boilerplates compared. The free tiers worth protecting are in free AI API tiers, and more tools are in the Developer tools directory.