Email List Cleaning Service
Remove invalid, disposable, and risky addresses with real-time SMTP verification
Email lists decay at roughly 22% per year as people change jobs and providers. Our API checks each address via live SMTP, MX records, and disposable-domain databases so you send only to inboxes that exist — reducing bounce rates, protecting sender reputation, and cutting ESP costs.
| Email Address | Status | Reachable | Flags |
|---|
What Gets Removed From Your Email List
Six-layer verification catches every category of bad address before it reaches your ESP.
SMTP Inbox Verification
A live SMTP handshake confirms the specific inbox exists on the recipient's mail server — not just that the domain accepts email. Catches invalid addresses that pass MX checks alone.
MX Record Validation
Checks DNS mail exchange records to confirm the domain is properly configured to receive email. Removes addresses on domains with no mail infrastructure.
Disposable Email Filtering
Matches against a continuously updated database of 10,000+ temporary and throwaway email providers (Mailinator, Guerrilla Mail, etc.) updated every 12 hours.
Role Account Detection
Flags addresses like admin@, noreply@, support@, and info@ that belong to teams rather than individuals. These rarely convert and often generate spam complaints.
Catch-All Domain Detection
Identifies domains configured to accept all incoming email regardless of whether the specific mailbox exists. Catch-all addresses look valid but produce unpredictable delivery results.
Typo Correction
Detects common domain misspellings (gmial.com, yhaoo.com, hotmial.com) and returns the likely intended address so you can correct signup data at source.
How Email List Cleaning Works
Three steps from dirty list to deliverable list — via API or CSV in minutes.
Upload Your List
Send a JSON array or upload a CSV file to the batch endpoint. Up to 100 addresses per request, up to 300,000 per month on the Enterprise plan. The first column of your CSV is used automatically; headers are detected and skipped.
SMTP Verification Runs
Each address is checked in parallel: syntax rules, MX record lookup, live SMTP handshake, disposable-domain match, role-account pattern, and catch-all probe. Addresses are processed concurrently — a 100-email batch typically completes in under 60 seconds.
Download Your Clean List
The API returns a JSON object with per-address results including
reachable, smtp.deliverable, disposable,
role_account, and smtp.catch_all flags. Filter to
reachable: "yes" and disposable: false to get your clean list.
The tool above generates a ready-to-download CSV.
Why Email List Hygiene Matters
Every invalid address you send to is a wasted cost, a bounce event, and a signal to ISPs that your sending practices need scrutiny.
Keep Bounce Rates Under 2%
Major ESPs including Mailchimp and SendGrid flag accounts when hard bounce rates exceed 2%. Once flagged, deliverability suffers for all subsequent sends — including to your valid subscribers. Regular list cleaning keeps your bounce rate well below that threshold.
Cut Email Sending Costs
Most ESPs charge by list size or email volume. B2B email lists typically contain 15–25% invalid addresses within six months of collection. Removing those addresses before your next send directly reduces the quantity you're billed for — with no impact on reach.
Protect Your Sender Reputation
ISPs and spam filters use bounce rates, complaint rates, and engagement signals to score your sender domain and IP. Consistently sending to stale or invalid addresses trains filters to treat your emails as low-quality, causing inbox placement to decline over time.
Improve Open and Click Rates
Sending to a smaller, verified list produces higher open rates — which in turn improves inbox placement in subsequent sends, creating a positive feedback loop. Cleaned lists consistently outperform uncleaned ones on engagement metrics.
Typical Use Cases
Teams that depend on list quality use email cleaning at every stage of their data lifecycle.
Marketing Teams
Clean lists before campaign sends to maximise deliverability and reduce ESP overage charges.
RevOps & CRM
Validate imported contact exports from LinkedIn, trade show scans, and form submissions.
Cold Outreach
Scrub prospect lists before sequences to stay below bounce thresholds and protect domain reputation.
SaaS Onboarding
Validate email at signup with the single-address endpoint, then re-verify dormant accounts in bulk.
Clean Your Email List via API
Two batch endpoints — JSON array for programmatic integration, CSV multipart upload for file-based workflows. Quota is deducted only on successful completion; failed batches cost nothing.
POST /api/v1/email/advanced/batch
curl -X POST "https://ip-api.io/api/v1/email/advanced/batch" \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{"emails": ["alice@example.com", "test@mailinator.com", "bob@company.org"]}'
{
"results": {
"alice@example.com": {
"reachable": "yes",
"smtp": {
"deliverable": true,
"catch_all": false,
"host_exists": true
},
"disposable": false,
"role_account": false,
"has_mx_records": true,
"free": false
},
"test@mailinator.com": {
"reachable": "no",
"smtp": {
"deliverable": false,
"catch_all": false,
"host_exists": true
},
"disposable": true,
"role_account": false,
"has_mx_records": true,
"free": false
}
}
}
POST /api/v1/email/advanced/batch/csv
# Upload a CSV file — first column is used, headers auto-detected
curl -X POST "https://ip-api.io/api/v1/email/advanced/batch/csv" \
-H "X-Api-Key: YOUR_API_KEY" \
-F "file=@email_list.csv"
{
"results": {
"alice@example.com": {
"reachable": "yes",
"smtp": {
"deliverable": true,
"catch_all": false,
"host_exists": true
},
"disposable": false,
"role_account": false,
"has_mx_records": true,
"free": false
},
"test@mailinator.com": {
"reachable": "no",
"smtp": {
"deliverable": false,
"catch_all": false,
"host_exists": true
},
"disposable": true,
"role_account": false,
"has_mx_records": true,
"free": false
}
}
}
POST /api/v1/email/advanced/batch
const API_KEY = "YOUR_API_KEY";
async function cleanEmailList(emails) {
const response = await fetch(
"https://ip-api.io/api/v1/email/advanced/batch",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": API_KEY
},
body: JSON.stringify({ emails })
}
);
if (!response.ok) throw new Error(`API error: ${response.status}`);
const { results } = await response.json();
return Object.entries(results).reduce(
(acc, [email, data]) => {
if (data.reachable === "yes" && !data.disposable) {
acc.clean.push(email);
} else if (data.reachable === "unknown" || data.smtp?.catch_all) {
acc.risky.push(email);
} else {
acc.invalid.push(email);
}
return acc;
},
{ clean: [], risky: [], invalid: [] }
);
}
cleanEmailList(["alice@example.com", "test@mailinator.com"])
.then(({ clean, risky, invalid }) => {
console.log(`Clean: ${clean.length}, Risky: ${risky.length}, Invalid: ${invalid.length}`);
});
{
"results": {
"alice@example.com": {
"reachable": "yes",
"smtp": {
"deliverable": true,
"catch_all": false,
"host_exists": true
},
"disposable": false,
"role_account": false,
"has_mx_records": true,
"free": false
},
"test@mailinator.com": {
"reachable": "no",
"smtp": {
"deliverable": false,
"catch_all": false,
"host_exists": true
},
"disposable": true,
"role_account": false,
"has_mx_records": true,
"free": false
}
}
}
POST /api/v1/email/advanced/batch
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://ip-api.io/api/v1/email/advanced"
def clean_email_list(emails):
"""Verify a list of emails and return only deliverable addresses."""
response = requests.post(
f"{BASE_URL}/batch",
headers={"X-Api-Key": API_KEY},
json={"emails": emails}
)
response.raise_for_status()
results = response.json()["results"]
clean, risky, invalid = [], [], []
for email, data in results.items():
if data.get("reachable") == "yes" and not data.get("disposable"):
clean.append(email)
elif data.get("reachable") == "unknown" or data.get("smtp", {}).get("catch_all"):
risky.append(email)
else:
invalid.append(email)
return {"clean": clean, "risky": risky, "invalid": invalid}
emails = ["alice@example.com", "test@mailinator.com", "bob@company.org"]
result = clean_email_list(emails)
print(f"Clean: {len(result['clean'])}, Risky: {len(result['risky'])}, Invalid: {len(result['invalid'])}")
{
"results": {
"alice@example.com": {
"reachable": "yes",
"smtp": {
"deliverable": true,
"catch_all": false,
"host_exists": true
},
"disposable": false,
"role_account": false,
"has_mx_records": true,
"free": false
},
"test@mailinator.com": {
"reachable": "no",
"smtp": {
"deliverable": false,
"catch_all": false,
"host_exists": true
},
"disposable": true,
"role_account": false,
"has_mx_records": true,
"free": false
}
}
}
POST /api/v1/email/advanced/batch
$apiKey = "YOUR_API_KEY";
$emails = ["alice@example.com", "test@mailinator.com", "bob@company.org"];
$response = file_get_contents(
"https://ip-api.io/api/v1/email/advanced/batch",
false,
stream_context_create([
"http" => [
"method" => "POST",
"header" => "Content-Type: application/json\r\nX-Api-Key: $apiKey",
"content" => json_encode(["emails" => $emails])
]
])
);
$results = json_decode($response, true)["results"];
$clean = array_filter($results, fn($d) => $d["reachable"] === "yes" && !$d["disposable"]);
echo count($clean) . " deliverable addresses";
{
"results": {
"alice@example.com": {
"reachable": "yes",
"smtp": {
"deliverable": true,
"catch_all": false,
"host_exists": true
},
"disposable": false,
"role_account": false,
"has_mx_records": true,
"free": false
},
"test@mailinator.com": {
"reachable": "no",
"smtp": {
"deliverable": false,
"catch_all": false,
"host_exists": true
},
"disposable": true,
"role_account": false,
"has_mx_records": true,
"free": false
}
}
}
JSON Request Body
{
"emails": [
"alice@example.com",
"test@mailinator.com",
"bob@company.org"
]
}
{
"results": {
"alice@example.com": {
"reachable": "yes",
"smtp": {
"deliverable": true,
"catch_all": false,
"host_exists": true
},
"disposable": false,
"role_account": false,
"has_mx_records": true,
"free": false
},
"test@mailinator.com": {
"reachable": "no",
"smtp": {
"deliverable": false,
"catch_all": false,
"host_exists": true
},
"disposable": true,
"role_account": false,
"has_mx_records": true,
"free": false
}
}
}
Pricing
Subscribe to clean up to 300,000 email addresses per month via API or CSV upload. Same plans cover IP geolocation, advanced email validation, and risk scoring — one API key for everything.
Note: Your API key will be sent to your email after the subscription is confirmed.
Email List Cleaning — Frequently Asked Questions
Everything you need to know about email hygiene, list scrubbing, and SMTP verification.
What is email list cleaning?
Email list cleaning — also called email list scrubbing or
email hygiene — is the process of removing invalid, undeliverable,
and risky addresses from a mailing list before sending. This includes addresses
that bounce (invalid syntax, no MX records, non-existent inboxes), disposable or
temporary email addresses, role-based accounts like admin@ and
noreply@, and catch-all domains that accept any address regardless of
whether it exists.
How does email list cleaning work?
Each address is checked in a series of steps: (1) syntax validation against RFC 5321/5322 rules, (2) MX record lookup to confirm the domain has mail infrastructure, (3) a live SMTP handshake with the recipient's mail server to verify the specific inbox exists, (4) matching against a database of known disposable and temporary email providers, and (5) pattern matching for role-based accounts. The result is a deliverability verdict — typically reachable, not reachable, or unknown — plus individual flags for each check.
How often should I clean my email list?
Most email marketers clean their lists every 3–6 months, or before any large campaign send. B2B lists decay faster than B2C — roughly 22% of business email addresses become invalid each year as people change jobs. As a practical rule: clean before any send to a list that hasn't been mailed in 90 days, and clean monthly if you're importing new contacts from trade shows, LinkedIn exports, or lead generation forms.
What is the difference between email list cleaning and email validation?
Email validation typically refers to checking a single address in real time — for example, at signup to reject typos and disposable addresses before they enter your database. Email list cleaning refers to batch-processing an existing list to remove accumulated invalid contacts. The underlying SMTP checks are the same, but the workflow differs: validation is a real-time gate at data entry, while list cleaning is periodic maintenance applied to stored contacts. See our Advanced Email Validation API for single-address real-time checking.
Does the API support CSV file upload?
Yes. The POST /api/v1/email/advanced/batch/csv endpoint accepts a
multipart form with a CSV or plain text file up to 1MB per request. The first column
is used as the email address; header rows are detected and skipped automatically.
For files larger than 1MB, split them and send multiple requests, then merge the
results.
What is a catch-all domain and should I remove those addresses?
A catch-all domain is configured to accept all incoming email regardless of whether a specific mailbox exists — so SMTP verification cannot confirm the individual inbox. They're common in enterprise and government domains (where the address is often real), but also used to capture harvested emails. A conservative approach is to treat them as risky: keep them in a separate segment and monitor bounce rates before sending at full volume.
What is email hygiene?
Email hygiene is the ongoing practice of maintaining a high-quality list by regularly removing invalid and unresponsive contacts, monitoring bounce and complaint rates, and keeping data current. Good hygiene includes: removing hard bounces immediately after each send, cleaning the full list every 3–6 months with SMTP verification, suppressing contacts who haven't opened any email in 12+ months, and validating new addresses at the point of collection.
How accurate is SMTP email verification?
SMTP verification is the most accurate method available for confirming inbox existence, with accuracy typically cited at 95%+ for non-catch-all domains. The main limitation is catch-all servers, which always accept SMTP connections, and greylisting — temporary rejections that look like failures. For non-catch-all domains, SMTP reliably distinguishes between existing and non-existing inboxes.
Ready to clean your email list?
Subscribe to verify up to 300,000 addresses per month via API or CSV upload. Reduce bounce rates, cut ESP costs, and protect your sender reputation.