
A disposable email checker tells you whether an address comes from a temporary inbox service, the kind people use once and then abandon. To check one address, paste it into our free email verifier and look at the "Temporary Email" row. It works as a temporary email checker with no signup.
This guide covers both jobs: checking a single address right now, and blocking disposable addresses automatically at signup with the API. It also explains exactly how the check works and where it can miss.
POST /email/validate) and reject the address when the result's description array contains disposable.A disposable email address (also called a throwaway, temporary or burner email address) is an inbox that's meant to be used briefly and then dropped. Well-known examples are Mailinator, Guerrilla Mail, 10 Minute Mail, YOPmail and Temp Mail.
People use them for understandable reasons:
For you as the sender, the problem is the same in every case. The address may stop being read soon after signup, so your onboarding emails, receipts and password resets go nowhere, and the contact still sits on your list.
A throwaway email checker can't read anyone's intent. What it can do is recognize the domain. That's why most tools, ours included, work as a disposable email domain checker: they look at the part after the @ and compare it with a list of domains known to belong to disposable services.
The free email verifier runs the full validation on one address, including the disposable check.
The Temporary Email row shows "yes" when the address was flagged as disposable and "no" when it wasn't. A flagged address shows a low score in red: 2 / 10 at most, and often 1 / 10, because many disposable services also accept mail for any address (more on the scoring below).
You can run 5 free validations per hour without signing up. In the tool's own words: "Email addresses are validated in real-time and not stored. Validation logs are retained for up to 30 days for debugging purposes."
If you want the broader picture of what makes an address valid (syntax, MX records, mailbox), see our guide on how to check if an email is valid.
Some vendors keep their detection method private. QuickEmailVerification, for example, says it doesn't disclose its process so disposable providers can't work around it. We think knowing what the check does helps you decide what to do with the result, so here it is.

The list. Our validator builds its disposable-domain list from two live sources and merges them:
The refresh. The list is rebuilt when the service starts and then every 6 hours. If both live sources are unreachable at the same time, the validator falls back to a list bundled with the service, so the check keeps working, just with older data.
The match. The validator takes the domain part of the address, lowercases it, and looks for an exact match in the list. A match adds disposable to the result's description and sets the classifier to risky.
The score. A disposable match subtracts 8 from the score. An address that passes every other check starts at 10, so it lands at 2, which our API reference describes as "Email can be used, but looks like a SPAM Trap or temporary email address." Many disposable services accept mail for any address, so they also get the catch-all deduction of 1 and land at 1. Other issues push the score lower still (it never drops below 0).
The disposable check runs as part of the full validation: syntax, MX records, mailbox, blacklist, catch-all and role checks, all scored from 0 to 10. That's why a single request tells you both "is this a burner?" and "will mail to it even arrive?"
Checking by hand doesn't scale to a signup form. The disposable email checker API is the POST /email/validate endpoint, which runs the full validation described above. Send the address at signup and reject it when the disposable flag is set.

You need an API key. Create a free account (200 free validations, no credit card) and add a key under Profile, in the API Keys section. Each validation uses 1 credit.
curl --request POST \
--url 'https://api.campaignkit.cc/v1/email/validate' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{ "emails": ["jane@mailinator.com"] }'
For this Mailinator address, the response looks like this. Mailinator accepts mail for any address, so the result also carries the catch-all flag:
{
"creditsUsed": 1,
"results": [
{
"email": "jane@mailinator.com",
"result": {
"syntax": "pass",
"mx": "pass",
"mailbox": "pass",
"score": 1,
"description": ["catchAll", "disposable"],
"classifier": "risky",
"smtpResponse": ""
}
}
]
}
The score and the other entries in description can differ from address to address. The disposable entry is what tells you the domain was matched, so check for that instead of a score threshold.
This script works in Node.js 18 or later (it uses the built-in fetch). Save it as check-disposable.mjs:
// check-disposable.mjs
// Usage: CAMPAIGNKIT_API_KEY=your_key node check-disposable.mjs someone@example.com
const API_URL = "https://api.campaignkit.cc/v1/email/validate";
export async function checkSignupEmail(email) {
const response = await fetch(API_URL, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CAMPAIGNKIT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ emails: [email] }),
// Don't keep a signup form waiting on a slow check.
signal: AbortSignal.timeout(5000),
});
if (!response.ok) {
// 400 = bad request, 402 = out of credits, and so on.
throw new Error(`CampaignKit API returned ${response.status}`);
}
const { results = [] } = await response.json();
const result = results[0]?.result;
const description = result?.description || [];
if (description.includes("disposable")) {
return { allow: false, reason: "disposable" };
}
// A blacklisted local part is reported instead of the disposable flag,
// and "invalid" means mail to the address will bounce.
if (description.includes("blacklist") || result?.classifier === "invalid") {
return { allow: false, reason: result.classifier === "invalid" ? "invalid" : "blacklist" };
}
return { allow: true, reason: null };
}
const email = process.argv[2];
if (!email) {
console.error("Usage: node check-disposable.mjs someone@example.com");
process.exit(1);
}
try {
const decision = await checkSignupEmail(email);
console.log(JSON.stringify(decision));
} catch (err) {
// Fail open: if the check can't run, let the signup through.
console.error(`Validation failed: ${err.message}`);
console.log(JSON.stringify({ allow: true, reason: "check_failed" }));
}
In your app, import checkSignupEmail into the signup handler (and drop the command-line part at the bottom). When allow is false with reason disposable, show a message such as "Please use a permanent email address," rather than failing silently.
The script fails open: if the API is unreachable, times out or returns an error, the signup goes through. That keeps an outage from locking out real users. If you'd rather fail closed, return { allow: false } in the catch block instead.
Run the script with a disposable address, then with one you know is real:
CAMPAIGNKIT_API_KEY=your_key node check-disposable.mjs jane@mailinator.com
# {"allow":false,"reason":"disposable"}
CAMPAIGNKIT_API_KEY=your_key node check-disposable.mjs you@yourcompany.com
# {"allow":true,"reason":null}
For a production example, our Auth0 pre-user registration action uses the same disposable check to block signups in Auth0, with a user-facing error message and a 5-second timeout. The full request and response reference is in the email validation API docs.
Can a disposable email checker miss a new domain or flag a real one? Yes, both can happen with any list-based check, including ours. Here's where and what to do about it.
A brand-new disposable domain isn't flagged. New disposable domains keep appearing, and a domain can only be matched once it's on one of the lists. The 6-hour refresh shortens the gap between a domain being listed and our validator knowing about it, but it doesn't remove it. If signups from a domain you suspect keep getting through, a confirmation email before activation catches addresses nobody reads.
A custom or self-hosted domain is used like a burner. Detection is domain-based. Someone who runs their own domain and creates throwaway addresses on it looks like any other private domain, so it won't get the disposable flag.
A real user's domain is flagged. If a domain ends up on a disposable list, every address on it gets the flag, whoever uses it. If a legitimate user reports this, you can allow that domain in your own signup code. The GitHub blocklist also takes corrections through issues and pull requests.
Subdomains aren't matched automatically. The match is exact on the domain. An address at a subdomain of a listed domain is only flagged if that subdomain is listed too.
The flag is missing even though the domain is disposable. A few results skip the disposable flag by design:
invalid with domain in description. Mail to it bounces anyway.invalid with mailbox.blacklist instead of disposable.verifyRejected, without the disposable check.The Node.js example above blocks the first three. A timed-out result is classified valid, so the example lets it through; a confirmation email at signup covers that gap.
Catch-all is not the same as disposable. A catch-all domain accepts mail for any address, so the mailbox can't be confirmed. That's a separate check with its own flag, and plenty of catch-all domains belong to ordinary companies. Don't treat a catch-all result as a burner.
To check an address right now, use the free disposable email checker in our email verifier. There's no signup, and you get 5 free validations per hour.
To block disposable signups automatically, start with 200 free validations, no credit card required. After that, credits start at $6 for 2,500 emails and never expire. Disposable email detection is included on every plan.
Start with 200 free validations. Upgrade only when you're ready.
No credit card required • Cancel anytime