Verifying a single email address takes under two seconds. Verifying fifty thousand of them, one at a time, would take you the better part of a month. That is not a realistic workflow for anyone managing a real email list.
Bulk email verification exists to solve this exact problem. You upload your entire list -- ten thousand, fifty thousand, or a hundred thousand addresses -- and the system processes them all in parallel, returning a categorized report that tells you which addresses are safe to send to, which ones will bounce, and which ones carry risk.
This guide walks through the complete bulk verification process: how to prepare your CSV file, how to upload it (both through the dashboard and the API), how to interpret the results, and what to do with each category of address. If you are new to email verification in general, start with What Is Email Verification and Why Does It Matter for the foundational concepts.
When You Need Bulk Verification
Single email verification works well at the point of entry -- a signup form, a lead capture widget, a checkout page. But there are situations where checking addresses one at a time is impractical.
Inherited or imported lists. You have acquired a list through a CRM migration, a company merger, a purchased database, or a partnership. You have no idea what percentage of these addresses are valid. Checking them in bulk is the only realistic option.
Periodic list hygiene. Email databases decay at roughly 22-25% per year. Even if you verified every address at the point of collection, a list that has not been cleaned in six months will have accumulated thousands of dead addresses. Our guide on how to clean your email list covers the full hygiene process, but bulk verification is the core mechanical step.
Pre-campaign scrubbing. Before a large email campaign -- a product launch, a seasonal promotion, a re-engagement sequence -- running your send list through bulk verification catches addresses that have gone stale since your last cleanup. This protects your sender reputation when it matters most.
Re-engagement campaigns. You have a segment of subscribers who have not opened or clicked in months. Before sending a re-engagement email to that segment, you should verify the addresses first. Many of those subscribers are not disengaged -- their mailboxes simply no longer exist.
Step 1: Prepare Your CSV File
The quality of your bulk verification depends heavily on how well you prepare your input file. A poorly formatted CSV will cause parsing errors, wasted credits, or incomplete results.
File Requirements
| Requirement | Specification |
|---|---|
| File format | CSV (comma-separated values) |
| Encoding | UTF-8 (not UTF-8 BOM, not Windows-1252) |
| Maximum file size | 10 MB |
| Maximum rows | 100,000 email addresses |
| Email column | Must contain one email address per row |
| Header row | Required -- the first row must contain column names |
Column Format
Your CSV must include a column containing email addresses. The column name is flexible -- EmailKit recognizes common names like email, Email, email_address, Email Address, and e-mail. If your column uses a non-standard name, you can map it during the upload process.
Your CSV can contain other columns (name, company, phone number, custom fields). EmailKit will ignore non-email columns during verification but preserve them in the results file, so you get your original data back alongside the verification verdicts.
Here is a minimal valid CSV:
email
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
And here is a CSV with additional columns that will be preserved:
first_name,last_name,email,company
John,Smith,[email protected],Acme Corp
Sarah,Lee,[email protected],TechStart Inc
Mike,Jones,[email protected],N/A
Common Preparation Mistakes
Duplicate addresses. If your file contains 5,000 duplicates, you pay for 5,000 verifications that return identical results. Deduplicate your file before uploading. A simple way in any spreadsheet application: sort by the email column, then remove duplicates.
Mixed encoding. If your CSV was exported from an older CRM or a Windows application, it may use Windows-1252 or Latin-1 encoding instead of UTF-8. Addresses with international characters (accented names in the local part) may be garbled. Open the file in a text editor that displays encoding (VS Code, Sublime Text, Notepad++) and re-save as UTF-8 if necessary.
Extraneous whitespace. Leading or trailing spaces in email cells ( [email protected]) can cause false negatives. Most verification systems trim whitespace, but it is good practice to clean it yourself. In Google Sheets, =TRIM(A1) handles this.
Invalid rows without email data. Empty rows, rows where the email cell is blank, or rows containing non-email text (like "N/A" or "none") will be skipped during verification but still count against your row limit. Remove them before uploading.
Step 2: Upload via the EmailKit Dashboard
The simplest way to run bulk verification is through the EmailKit web dashboard.
Upload Process
- Sign in to your EmailKit account and navigate to the Bulk Verify page.
- Click the upload area or drag and drop your CSV file. The system validates the file format and size immediately -- if your file exceeds 10 MB or 100,000 rows, you will see an error before any processing begins.
- EmailKit scans the file headers and identifies the email column. If it cannot auto-detect the correct column, a dropdown lets you select which column contains email addresses.
- Review the summary: total rows detected, estimated credits required, and any warnings about duplicate or malformed addresses.
- Click "Start Verification" to submit the job.
What Happens After Submission
Bulk verification is asynchronous. Unlike single email verification, which returns a result in under two seconds, a bulk job runs in the background. Here is what the process looks like from your side:
- Queued. Your job enters the processing queue. If other users have submitted bulk jobs, yours will be processed fairly -- EmailKit uses round-robin scheduling across tenants so no single user monopolizes the system.
- Processing. The system works through your list, verifying each address through the same multi-layer checks used for single verification: syntax validation, domain and MX record lookup, SMTP handshake, disposable email detection, and catch-all domain identification. A real-time progress bar updates on the dashboard via Server-Sent Events (SSE).
- Completed. Once every address has been checked, the job status changes to "Completed" and your results become available for download.
Processing Speed
Processing speed depends on list size and current system load, but typical throughput is several thousand verifications per minute. A 10,000-address list usually completes in under five minutes. A 100,000-address list typically finishes in 30-60 minutes.
The variable that most affects speed is the responsiveness of the mail servers being checked. Addresses at major providers (Gmail, Outlook, Yahoo) verify quickly because those servers respond to SMTP handshakes immediately. Addresses at smaller or self-hosted domains may take longer if their mail servers are slow to respond or impose connection-level rate limits.
Step 3: Upload via the API (For Developers)
If you are integrating bulk verification into an automated pipeline -- a nightly list cleanup job, a CRM export workflow, or a CI/CD quality gate -- you can use the EmailKit API directly.
Submit a Bulk Job
POST https://api.emailkit.dev/api/v1/verify/bulk
Content-Type: application/json
Authorization: Bearer ek_your_api_key
{
"emails": [
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]"
]
}
The API endpoint accepts a JSON array of email addresses. The response returns a job ID that you use to track progress and retrieve results:
{
"jobId": "bulk_abc123def456",
"status": "queued",
"totalEmails": 4,
"createdAt": "2026-02-28T10:30:00Z"
}
Poll Job Status
Bulk jobs are asynchronous. After submitting, poll the status endpoint until the job completes:
GET https://api.emailkit.dev/api/v1/verify/bulk/bulk_abc123def456
Authorization: Bearer ek_your_api_key
{
"jobId": "bulk_abc123def456",
"status": "processing",
"totalEmails": 4,
"processedEmails": 2,
"progress": 50,
"createdAt": "2026-02-28T10:30:00Z"
}
The status field will be one of: queued, processing, completed, or failed. Poll every 5-10 seconds for small jobs, every 30-60 seconds for large ones. Do not poll more frequently than once per second.
Download Results
Once the job status is completed, retrieve the full results:
GET https://api.emailkit.dev/api/v1/verify/bulk/bulk_abc123def456/results
Authorization: Bearer ek_your_api_key
The results endpoint returns the verification verdicts for every address in the original submission. For large result sets, the response may be a pre-signed download URL that expires after one hour.
Full Workflow in Node.js
const API_BASE = "https://api.emailkit.dev/api/v1";
const API_KEY = "ek_your_api_key";
async function bulkVerify(emails) {
// 1. Submit the bulk job
const submitRes = await fetch(`${API_BASE}/verify/bulk`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ emails }),
});
const { jobId } = await submitRes.json();
console.log(`Job submitted: ${jobId}`);
// 2. Poll until complete
let status = "queued";
while (status !== "completed" && status !== "failed") {
await new Promise((resolve) => setTimeout(resolve, 10000));
const statusRes = await fetch(`${API_BASE}/verify/bulk/${jobId}`, {
headers: { "Authorization": `Bearer ${API_KEY}` },
});
const job = await statusRes.json();
status = job.status;
console.log(`Progress: ${job.progress}%`);
}
if (status === "failed") {
throw new Error("Bulk verification job failed");
}
// 3. Download results
const resultsRes = await fetch(`${API_BASE}/verify/bulk/${jobId}/results`, {
headers: { "Authorization": `Bearer ${API_KEY}` },
});
return resultsRes.json();
}
// Usage
const emails = ["[email protected]", "[email protected]", "[email protected]"];
const results = await bulkVerify(emails);
console.log(results);
Step 4: Understanding Your Results
Every email address in your bulk job receives one of four verdict categories. Understanding what each category means -- and what action to take -- is the difference between a properly cleaned list and a partially cleaned one.
Results Interpretation Table
| Category | What It Means | Action |
|---|---|---|
| Deliverable | The mailbox exists, the domain has valid MX records, and the SMTP handshake confirmed the address accepts mail. This is a high-confidence result. | Keep in your list. Safe to send. |
| Undeliverable | The address is definitively invalid. The mailbox does not exist, the domain has no MX records, or the SMTP server explicitly rejected the address. | Remove immediately. Sending to these addresses will generate hard bounces. |
| Risky | The address exists but carries elevated risk. This includes catch-all domains (where the server accepts mail for any address, making it impossible to confirm a specific mailbox), role-based addresses (info@, admin@, support@), disposable email addresses, and addresses with low sender reputation scores. | Handle with care. See the section below on risky addresses. |
| Unknown | The verification could not determine a definitive result. The mail server timed out, returned an ambiguous response, was temporarily unavailable, or implements greylisting that prevented a conclusive check. | Re-verify after 24-48 hours. Most unknowns resolve on retry. |
Typical Distribution
For a moderately maintained list (cleaned within the last 6-12 months), expect roughly this distribution:
- Deliverable: 70-85%
- Undeliverable: 5-15%
- Risky: 5-15%
- Unknown: 1-5%
If your undeliverable percentage is above 20%, your list has a serious hygiene problem. If your risky percentage is above 20%, you likely have a high concentration of catch-all domains or role-based addresses in your data.
For lists that have never been cleaned, or purchased lists, it is common to see 30-50% of addresses fall into the undeliverable or risky categories.
What To Do With Risky Addresses
Risky addresses require judgment, not a blanket keep-or-remove decision. The right approach depends on the specific risk flag:
Catch-all domains. The domain's mail server accepts mail for any address at that domain, so the verification system cannot confirm whether the specific mailbox exists. If these are business contacts at companies you have a real relationship with, keep them. If they are from a purchased list, remove them.
Role-based addresses. Addresses like info@, admin@, sales@, and support@ are typically shared mailboxes managed by multiple people. They tend to have lower engagement rates and higher complaint rates. Remove them from marketing campaigns but keep them for transactional or sales communication if they are legitimate business contacts.
Disposable addresses. These are from services like Guerrilla Mail, Temp Mail, and similar providers that create temporary inboxes. Remove them entirely. A person who used a disposable address intentionally avoided giving you their real email.
Low confidence scores. Some addresses pass SMTP checks but have other risk indicators (new domains, low domain reputation, patterns consistent with bot-generated addresses). Consider segmenting these into a separate group and monitoring their engagement after one send. If they do not engage, remove them.
What To Do With Unknown Addresses
Unknown results are not inherently bad. They are inconclusive. The most common causes:
- The destination mail server was temporarily unavailable
- The server uses greylisting (deliberately rejects the first connection attempt)
- The server timed out before completing the SMTP handshake
- Rate limiting by the destination server prevented verification
Re-verify unknown addresses 24-48 hours after your initial bulk job. Most of them will resolve to a definitive deliverable or undeliverable status on the second attempt. If an address returns unknown on two consecutive verification attempts, treat it as risky and apply the same judgment framework described above.
Step 5: Export Your Clean List
Once you have reviewed your results, export the cleaned list for use in your ESP, CRM, or marketing platform.
From the Dashboard
On the job results page, you have several export options:
- Download full results (CSV) -- Every address with its verification verdict, risk flags, and all original columns from your uploaded file.
- Download deliverable only (CSV) -- A filtered export containing only addresses that received a "deliverable" verdict. This is your ready-to-send list.
- Download by category -- Export specific categories separately if you want to handle risky or unknown addresses in different workflows.
Result downloads are generated as pre-signed URLs that remain valid for one hour. If the link expires, you can generate a new one from the job detail page.
From the API
The results endpoint returns all data needed to filter and process your list programmatically. You can filter the response by status in your own code and route addresses to the appropriate workflow -- clean addresses to your ESP, risky addresses to a review queue, undeliverable addresses to an archive or deletion pipeline.
Bulk Verification Best Practices
Deduplicate before uploading. This is the single easiest way to reduce costs. A list with 15% duplicates means 15% of your credits are wasted on redundant checks.
Verify before importing into your ESP. Run bulk verification on your list before uploading it to Mailchimp, SendGrid, ActiveCampaign, or any other email service. This avoids bounce-triggered penalties from your ESP.
Schedule regular verification. Set a cadence: monthly for high-volume senders (100K+ emails/month), quarterly for moderate senders. Decay does not wait for you to notice.
Keep your results. Store the full verification results alongside your contact records. When you re-verify in three months, comparing the new results against the old ones shows you the rate of list decay and helps you identify data sources that produce disproportionately low-quality addresses.
Verify in segments for very large lists. If you have more than 100,000 addresses, split your file into chunks of 100,000 or fewer. You can run multiple bulk jobs simultaneously -- they will be processed in parallel.
Use the API for recurring workflows. If you are running bulk verification on a regular schedule, the API is more efficient than manual CSV uploads. Integrate it into a cron job, a CRM export hook, or a data pipeline. The code example above provides a complete submit-poll-download workflow you can adapt.
Cost Considerations
Bulk verification consumes one credit per email address verified. Only addresses that are actually processed count against your balance -- if a row is skipped due to a blank email cell or a malformed address, no credit is charged.
Before starting a bulk job, the system performs a credit check. If you do not have enough credits to verify the entire file, the job will not start. You will see the exact credit requirement in the upload summary, giving you the opportunity to purchase additional credits before proceeding.
For large lists, EmailKit's volume pricing reduces the per-verification cost significantly. At the highest volume tier, the cost per email drops to a fraction of a cent. Check the billing page for current pricing.
Try Bulk Verification
If you have a list that needs cleaning -- whether it is 500 addresses or 100,000 -- bulk verification is the fastest way to separate the deliverable from the dead weight. Upload your CSV, let the system process it, and download a clean list ready for your next campaign.
Start your bulk verification now -- upload up to 100K emails per job.
Next up in this series: How Sender Reputation Works and Why It Matters -- understanding the scoring systems that ISPs use to decide whether your emails reach the inbox or the spam folder.