B2B Lead List Cleaner - Bulk Email Verification & Validator
Pricing
from $1.70 / 1,000 audited leads
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
Maintained by CommunityActor 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 rulesREVIEW: evidence is incomplete, uncertain, or below the acceptance thresholdREJECT: 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
| Result | What it tells you |
|---|---|
| One explained decision per delivered row | Route good leads and isolate uncertainty without a black-box score |
| Batch and historical duplicate flags | Find repeated contacts before CRM import |
| Email syntax and DNS MX evidence | Confirm domain-level mail configuration without claiming mailbox verification |
| Personal, disposable, and role-inbox classification | Apply a consistent inbox policy |
| Country, city, title, industry, and account rules | Enforce the ICP attached to a list order |
| Raw-row preservation and normalized fields | Keep source-specific data while gaining stable automation fields |
| Run report and source economics | Measure 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: truefor a duplicate in the current batchhistoricalDuplicate: truewhen the monitor has seen the lead beforeDUPLICATE_LEADorHISTORICAL_DUPLICATEinreasonCodes
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:
datasetId: an Apify dataset containing lead objects or email stringsemails: up to 5,000 email stringsrows: 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
| Mode | Base behavior |
|---|---|
BALANCED | Requires 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 |
STRICT | Adds role-inbox rejection, requires company-domain evidence, probes public websites, enables a 365-day freshness rule, and raises score thresholds |
CUSTOM | Starts 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, andreasonCodes- normalized contact and company fields
emailStatus,mxStatus, andwebsiteStatusduplicate,historicalDuplicate, anddedupeKey- typed
evidenceand orderedreasons normalizationTruncatedFieldsoriginal,originalPreserved, andoriginalByteLengthcheckedAtandschemaVersion
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 itsdedupeKey, 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_MXrejection carries the DNS lookup result insideevidence.email.mx, andmailboxExistencestaysNOT_CLAIMEDbecause no SMTP probing is performed. - Uncertainty is a verdict, not a coin flip. A role-based team inbox gets
REVIEWwith 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:
SUCCEEDEDPARTIAL_BUDGET_LIMITPARTIAL_DELIVERYSUCCEEDED_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 requestedSAVED: delivered dedupe keys were savedSAVE_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 enteredsourceCostScope: "AUDITED_ROWS": the declared scope was fully deliveredsourceCostScope: "INCOMPLETE_DELIVERY": safe allocation was not possible after partial deliverysourceCostPerAcceptedLeadUsd: 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
ACCEPTto the permitted downstream workflow - send
REVIEWto 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 plan | Price |
|---|---|
| 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.