Email List Cleaning API

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.

Real-time SMTP checks
CSV upload supported
Up to 300K emails / month — 95%+ accuracy
Clean a List

One email per line — add your API key below to verify more addresses

List Input
Up to 100 emails
SMTP Verify
Waiting…
Clean Output
Pending…
{ } JSON Response

          
        
Trusted by thousands of businesses
Fast JSON API responses
Real-time validation
Simple integration, SDKs & examples
Features

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 It Works

How Email List Cleaning Works

Three steps from dirty list to deliverable list — via API or CSV in minutes.

1

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.

2

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.

3

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.

Benefits

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.

Industry threshold: 2% bounce rate

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.

Save 15–25% on ESP bills

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.

Maintain domain health & inbox placement

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.

Higher engagement, better inbox placement
Use Cases

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.

Campaign hygiene ESP cost control

RevOps & CRM

Validate imported contact exports from LinkedIn, trade show scans, and form submissions.

CRM imports Lead enrichment

Cold Outreach

Scrub prospect lists before sequences to stay below bounce thresholds and protect domain reputation.

Prospecting Domain reputation

SaaS Onboarding

Validate email at signup with the single-address endpoint, then re-verify dormant accounts in bulk.

Signup validation Re-activation
Email Cleaning API

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.

Two batch endpoints — JSON array for programmatic integration, CSV multipart upload for file-based workflows. Both return per-address SMTP results in one synchronous response.
reachable — Overall verdict: "yes", "no", or "unknown"
smtp.deliverable — Live SMTP inbox confirmation
smtp.catch_all — Domain accepts all email; cannot confirm individual inbox
disposable — Matched against 10,000+ throwaway domains, updated every 12 hours
role_account — Role-based address (admin@, noreply@, support@, info@)
Up to 100 addresses per request; CSV upload accepts files up to 1 MB
Read API Reference
Endpoint
POST /api/v1/email/advanced/batch
Example Request
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"]}'
Example Response
200
{
  "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
    }
  }
}
Endpoint
POST /api/v1/email/advanced/batch/csv
Example Request
# 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"
Example Response
200
{
  "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
    }
  }
}
Endpoint
POST /api/v1/email/advanced/batch
Example Request
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}`);
  });
Example Response
200
{
  "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
    }
  }
}
Endpoint
POST /api/v1/email/advanced/batch
Example Request
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'])}")
Example Response
200
{
  "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
    }
  }
}
Endpoint
POST /api/v1/email/advanced/batch
Example Request
$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";
Example Response
200
{
  "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
    }
  }
}
Endpoint
JSON Request Body
Example Request
{
  "emails": [
    "alice@example.com",
    "test@mailinator.com",
    "bob@company.org"
  ]
}
Example Response
200
{
  "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

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.

Small
€10 /mo
100,000 geo ip requests
10,000 advanced email validation requests
Location data
Email validation
Risk score calculation
Currency data
Time zone data
Threat data
Unlimited support
HTTPS encryption
Get started
Medium
€20 /mo
300,000 geo ip requests
25,000 advanced email validation requests
Location data
Email validation
Risk score calculation
Currency data
Time zone data
Threat data
Unlimited support
HTTPS encryption
Get started

Note: Your API key will be sent to your email after the subscription is confirmed.

FAQ

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.