B2B Lead List Cleaner - Bulk Email Verification & Validator avatar

B2B Lead List Cleaner - Bulk Email Verification & Validator

Pricing

from $1.70 / 1,000 audited leads

Go to Apify Store
B2B Lead List Cleaner - Bulk Email Verification & Validator

B2B Lead List Cleaner - Bulk Email Verification & Validator

Bulk email verification and email list cleaning for B2B leads: an email validator and verifier that checks syntax and MX records, flags personal, disposable, and role inboxes, dedupes, and enforces ICP rules with an explained decision per row. Domain-level checks only; no SMTP mailbox pings.

Pricing

from $1.70 / 1,000 audited leads

Rating

0.0

(0)

Developer

Kamer Ozkan

Kamer Ozkan

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Categories

Share

Put an explained quality gate between a raw lead list and your CRM.

This Actor audits B2B lead rows before you spend more enrichment credits, outreach credits, or SDR time. For every row it successfully delivers, you receive one deterministic decision:

  • ACCEPT: the row passes the configured evidence and targeting rules
  • REVIEW: evidence is incomplete, uncertain, or below the acceptance threshold
  • REJECT: a hard quality, duplicate, or ICP rule failed

It checks email syntax, DNS mail routing, provider type, role inboxes, company-domain consistency, duplicates, freshness, and optional ICP rules. It does not connect to an SMTP server and does not claim that an individual mailbox exists.

Free plan: $2 per 1,000 audited leads. Plan discounts reduce this to as low as $1.70. No start fee.

What you get

ResultWhat it tells you
One explained decision per delivered rowRoute good leads and isolate uncertainty without a black-box score
Batch and historical duplicate flagsFind repeated contacts before CRM import
Email syntax and DNS MX evidenceConfirm domain-level mail configuration without claiming mailbox verification
Personal, disposable, and role-inbox classificationApply a consistent inbox policy
Country, city, title, industry, and account rulesEnforce the ICP attached to a list order
Raw-row preservation and normalized fieldsKeep source-specific data while gaining stable automation fields
Run report and source economicsMeasure delivered yield, reason mix, and audited-scope cost

Duplicate behavior

Duplicates are not silently removed.

The Actor keeps one output decision for every row it successfully delivers. A non-canonical duplicate remains in the output with:

  • decision: "REJECT"
  • duplicate: true for a duplicate in the current batch
  • historicalDuplicate: true when the monitor has seen the lead before
  • DUPLICATE_LEAD or HISTORICAL_DUPLICATE in reasonCodes

Each delivered decision, including a duplicate REJECT, is a billable lead-audited event. Route only ACCEPT rows downstream if you want a deduplicated usable list.

Supported inputs and priority

Choose one source:

  1. datasetId: an Apify dataset containing lead objects or email strings
  2. emails: up to 5,000 email strings
  3. rows: up to 5,000 JSON lead objects

If more than one source is supplied, the priority is datasetId, then emails, then rows.

Dataset runs can audit up to 25,000 rows per run. Use offset and maxItems to process larger sources in non-overlapping ranges. offset can be up to 10,000,000 and maxItems can be up to 25,000.

Dataset input

{
"datasetId": "YOUR_DATASET_ID",
"qualityMode": "BALANCED",
"offset": 0,
"maxItems": 25000
}

In Apify Console, select the dataset with the resource picker. The Actor receives read-only access to that dataset. No API token is normally needed inside the Console input form.

Email-string input

{
"emails": [
"ada@stripe.com",
"info@example.com",
"buyer@gmail.com"
],
"qualityMode": "BALANCED"
}

Each email string becomes a source object such as { "email": "ada@stripe.com" }. Email-only input can evaluate syntax, provider type, DNS mail routing, and duplicates. It cannot invent person, company, location, or employment evidence.

Pasted lead rows

{
"rows": [
{
"full_name": "Ada Rivera",
"job_title": "VP Marketing",
"email": "ada@stripe.com",
"country": "United States",
"company_name": "Stripe",
"company_domain": "stripe.com",
"industry": "Software"
}
]
}

Field detection and compatibility

The Actor detects common contact and company aliases, including nested paths such as contact.email, person.jobTitle, and company.website. The OUTPUT report shows:

  • the selected path for every normalized field
  • sampled coverage for that path
  • fields explicitly overridden with fieldMap

Use manual mapping when the report selects the wrong path:

{
"datasetId": "YOUR_DATASET_ID",
"fieldMap": {
"fullName": "contact.name",
"email": "contact.workEmail",
"title": "employment.currentTitle",
"companyDomain": "company.website"
}
}

This Actor works best with person-level B2B lead datasets. Dataset items that are plain strings are treated as emails. A place or company dataset, including many Google Maps outputs, may not contain a contact email or job title. Do not assume generic compatibility: inspect field coverage, map the real paths, and test a small range first.

Phone numbers and LinkedIn values are normalized and preserved, not verified. The Actor also does not verify current employment.

Quality modes

ModeBase behavior
BALANCEDRequires email and valid domain mail routing, rejects personal and disposable providers, rejects email-company domain mismatches, warns on role inboxes, and does not probe websites
STRICTAdds role-inbox rejection, requires company-domain evidence, probes public websites, enables a 365-day freshness rule, and raises score thresholds
CUSTOMStarts with the same preset as Balanced, then applies rule overrides

Rule overrides apply after every preset, not only Custom. This makes it possible to make one deliberate change without recreating the entire preset:

{
"qualityMode": "BALANCED",
"rules": {
"rejectRoleBasedEmail": true,
"acceptScore": 80
}
}

requireMx: true automatically enables MX checks. requireWebsiteReachable: true automatically enables safe website checks. reviewScore must remain lower than acceptScore.

Optional ICP contract

Use targeting rules when a source or vendor promised a specific audience:

{
"datasetId": "YOUR_DATASET_ID",
"targeting": {
"countries": ["United States"],
"cities": ["New York", "Boston"],
"titleKeywords": ["CMO", "VP Marketing", "Head of Growth"],
"excludedTitleKeywords": ["Assistant", "Intern"],
"industries": ["Software", "SaaS"],
"companyDomains": ["example.com"]
}
}

When a targeting list is configured, missing evidence is not treated as a match. It receives a specific missing-field or mismatch reason.

Output contract

The default dataset contains one object per delivered decision. Important fields include:

  • sourceIndex, decision, qualityScore, primaryReason, and reasonCodes
  • normalized contact and company fields
  • emailStatus, mxStatus, and websiteStatus
  • duplicate, historicalDuplicate, and dedupeKey
  • typed evidence and ordered reasons
  • normalizationTruncatedFields
  • original, originalPreserved, and originalByteLength
  • checkedAt and schemaVersion

All records below are unedited engine output from a live run on 2026-07-28. Every input row was a labeled sample (each fullName carries a "(sample)" suffix and each address uses an apify-task-demo local part), so no real person appears here; the MX evidence against the real domains is genuine.

A clean accepted lead, in full. Note original: the source row used work_email and job_title, and field detection mapped them without configuration.

The same run exercised the failure catalog. Three guarantees, three records:

  • Nothing is dropped silently. The duplicate row is delivered with duplicate: true, DUPLICATE_LEAD, and its dedupeKey, so your CRM sees why it was rejected instead of wondering where a row went.
  • A dead domain is proof, not a guess. The NO_MX rejection carries the DNS lookup result inside evidence.email.mx, and mailboxExistence stays NOT_CLAIMED because no SMTP probing is performed.
  • Uncertainty is a verdict, not a coin flip. A role-based team inbox gets REVIEW with named reasons, not a fake ACCEPT or a silent REJECT.
{
"sourceIndex": 1,
"decision": "REJECT",
"qualityScore": 30,
"primaryReason": "The same lead already appeared in this batch.",
"reasonCodes": [
"DUPLICATE_LEAD"
],
"fullName": "Jonas Weber (sample)",
"email": "apify-task-demo-501@asana.com",
"emailStatus": "BUSINESS",
"mxStatus": "VALID",
"duplicate": true,
"dedupeKey": "email:apify-task-demo-501@asana.com",
"originalPreserved": true
}
{
"sourceIndex": 3,
"decision": "REJECT",
"qualityScore": 45,
"primaryReason": "Email domain has no observable mail server records.",
"reasonCodes": [
"EMAIL_DOMAIN_NO_MX"
],
"fullName": "Tobias Lang (sample)",
"email": "apify-task-demo-503@apify-demo-no-mx-20260728.com",
"emailStatus": "BUSINESS",
"mxStatus": "NO_MX",
"duplicate": false,
"dedupeKey": "email:apify-task-demo-503@apify-demo-no-mx-20260728.com",
"originalPreserved": true,
"evidence": {
"email": {
"domain": "apify-demo-no-mx-20260728.com",
"mx": {
"status": "NO_MX",
"records": [],
"error": "NO_DNS"
},
"mailboxExistence": "NOT_CLAIMED",
"note": "remaining evidence fields unchanged, shortened here"
}
}
}
{
"sourceIndex": 6,
"decision": "REVIEW",
"qualityScore": 85,
"primaryReason": "Quality score is below the ACCEPT threshold.",
"reasonCodes": [
"QUALITY_SCORE_NEEDS_REVIEW",
"EMAIL_ROLE_BASED"
],
"fullName": "Outreach Desk (sample)",
"email": "hello@typeform.com",
"emailStatus": "ROLE_BASED",
"mxStatus": "VALID",
"duplicate": false,
"dedupeKey": "email:hello@typeform.com",
"originalPreserved": true
}

The same run also produced named rejections for a personal inbox (EMAIL_PERSONAL), a disposable domain (EMAIL_DISPOSABLE), and a missing address (EMAIL_MISSING); every non-accepted row leaves with a machine-readable reason code.

qualityScore is a rule-based completeness score, not a deliverability percentage.

mxStatus: "VALID" means usable public MX routing was observed. IMPLICIT_MX means the domain uses the standards-based address-record fallback. Neither result proves that the specific mailbox exists.

The complete source item is copied to original. If its serialized size exceeds 7,500,000 bytes, the Actor emits an omission marker, sets originalPreserved to false, and adds ORIGINAL_TOO_LARGE. Oversized normalized strings are shortened to safe limits and listed in normalizationTruncatedFields.

The original source item and dedupeKey can contain personal data. Treat output storage, export, access, and deletion accordingly.

Run-level report

The default key-value store record OUTPUT includes:

  • delivered ACCEPT, REVIEW, and REJECT counts and rates
  • duplicate counts and reason frequencies
  • source type, offset, loaded rows, truncation, and budget effects
  • resolved rules and targeting
  • field mapping and sampled coverage
  • history save status
  • billing and delivery integrity counters
  • explicit truth boundaries

Possible report statuses are:

  • SUCCEEDED
  • PARTIAL_BUDGET_LIMIT
  • PARTIAL_DELIVERY
  • SUCCEEDED_WITH_WARNINGS

Always check status, source.deliveredItems, and billing.delivered before treating a run as complete.

Historical duplicate protection

Set monitorName for a recurring, non-overlapping workflow:

{
"datasetId": "YOUR_DATASET_ID",
"monitorName": "us-saas-outbound"
}

The monitor stores SHA-256 hashes of normalized deduplication keys in a named Apify key-value store. Hashes are pseudonymized, not anonymous or encrypted. The decision dataset still contains the normalized dedupeKey and usually the original source row.

Named key-value stores are retained indefinitely until you delete them. History is capped at the newest 100,000 hashes. Use separate monitor names for separate business purposes and delete stores according to your retention policy.

Do not overlap scheduled runs that use the same monitorName. Each run evaluates historical duplicates from the snapshot available when it starts, so overlapping runs can both classify a newly seen lead as new.

The report distinguishes:

  • DISABLED: no monitor requested
  • SAVED: delivered dedupe keys were saved
  • SAVE_WARNING: decisions were delivered, but history could not be updated

If history returns SAVE_WARNING, fix or retry the history step before the next scheduled run.

Source economics

rules.sourceCostUsd must be the source cost attributable to the rows requested for this audit:

{
"datasetId": "YOUR_DATASET_ID",
"offset": 10000,
"maxItems": 5000,
"rules": {
"sourceCostUsd": 50
}
}

Do not enter the cost of the entire source batch unless the run audits that entire batch. The report uses:

  • sourceCostProvidedUsd: the value you entered
  • sourceCostScope: "AUDITED_ROWS": the declared scope was fully delivered
  • sourceCostScope: "INCOMPLETE_DELIVERY": safe allocation was not possible after partial delivery
  • sourceCostPerAcceptedLeadUsd: calculated only for a complete audited scope with at least one ACCEPT

This is a supplied cost allocation, not a value independently verified by the Actor.

API and automation

API calls require an Apify API token. Example:

curl -X POST \
"https://api.apify.com/v2/acts/kamerozkan~b2b-lead-cleaner/runs" \
-H "Authorization: Bearer YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"datasetId": "YOUR_DATASET_ID",
"qualityMode": "BALANCED",
"offset": 0,
"maxItems": 1000
}'

After the run finishes, read decision rows from the default dataset and the report from key OUTPUT in the default key-value store.

For Make, Zapier, n8n, webhooks, CRMs, or AI agents:

  • send ACCEPT to the permitted downstream workflow
  • send REVIEW to a manual or enrichment queue
  • archive or inspect REJECT
  • check the run report before advancing a whole batch

This Actor is also exposed to AI agents through Apify's MCP server (mcp.apify.com): an agent can discover it by search and run it with the same pay-per-event billing, with no separate integration.

Security and operational boundaries

  • source dataset access is read-only
  • private, local, and reserved network targets are never requested
  • website checks resolve and pin public addresses before requests
  • no SMTP mailbox probing is performed
  • no mailbox ownership, current employment, or reply is guaranteed
  • original source rows are copied to output unless the size guard omits them
  • monitor history is pseudonymized and persists until deleted
  • rows prevented by the run budget are not delivered or charged

Pricing

One lead-audited event represents one delivered ACCEPT, REVIEW, or REJECT quality decision. Current prices per 1,000 audited leads are:

Apify planPrice
Free$2.00
Bronze$1.90
Silver$1.80
Gold, Platinum, or Diamond$1.70

The active pricing model has no Actor start event. Apify shows the exact price for the user's plan before every run.

There is no start fee. Rows blocked by the Apify run budget are not delivered or charged.

Responsible use

Process only data you are authorized to use. Follow applicable privacy, marketing, and anti-spam laws, including GDPR, CAN-SPAM, and local equivalents. A technical quality decision does not create a lawful basis for outreach.