Lead List Verifier: Phone, Website, MX, Duplicates
Pricing
from $1.50 / 1,000 lead verifieds
Lead List Verifier: Phone, Website, MX, Duplicates
Verify a lead list after any scraper: phones to E.164 with line type, websites checked as live, redirected, parked or dead, mail servers, duplicates and a 0 to 100 score with reasons. Keeps every original field. Reads a dataset or pasted records and is built to run as an integration after a scraper.
Pricing
from $1.50 / 1,000 lead verifieds
Rating
0.0
(0)
Developer
VER RR
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Security
Limited permissionsShare
Lead List Verifier runs after any lead scraper and shows which rows are worth keeping: each record comes back with its fields intact, with its phone, website, mail servers and duplicates checked and a 0 to 100 score.
What data you get
Every field of your record, plus one verification object:
verification.index: the record's position in the run's input, from 0. Dataset rows come first, then pasted records.verification.phone:e164(the number in E.164, or null),valid(true or false) andlineType(such asmobile,fixed_line,fixed_line_or_mobile,toll_free,voip, or null when not known).verification.domain: the canonical registrable domain, such asacme.co.ukforhttps://www.acme.co.uk/shop. Null when the record has no own website.verification.websiteStatus:live,redirected,parked,dead,no_websiteorunknown.verification.finalUrl: where the site ended up, when it went to another domain. Otherwise null.verification.mx: true if the domain has mail servers, false if it has none, null if there is no domain or the lookup failed.verification.duplicateOf: theindexof the first record in the output with the same domain, the same phone, or the same name and city. Otherwise null.verification.score: 0 to 100.verification.reasons: every line that moved the score, in plain words.verification.checkedAt: when the record was checked.
If a record already has a field called verification, it is kept as sourceVerification and the run log says so.
What each website status means
| Status | Meaning |
|---|---|
live | The homepage answered with a page, on the same domain. If https failed and plain http answered, the site still reads live, and reasons names the https failure. |
redirected | The site sends visitors to another domain. finalUrl shows where. |
parked | Parking name servers, a redirect to a domain marketplace, a parking network's code in the page, or a near-empty page that offers the domain for sale or is a host's stock page. |
dead | There is proof: the domain has no address in DNS, or every route to it answers 404 or 410. |
no_website | The record has no website, its value is not a web address, or it is only a page on a shared platform: a social site, a directory, a booking or ordering platform, or a hosted site builder. |
unknown | We could not tell. The reason is in reasons. |
unknown is not dead. A site that blocks us, asks for a CAPTCHA, times out, resets or refuses the connection, has an empty homepage, or is closed to us by robots.txt is unknown, and so is a bad certificate with no working plain http, because any of those can happen to a healthy site. A 404 on one route never overrules a failure on another. We do not retry through proxies or work around a block.
A page on a shared platform is not fetched, gets no domain and no mx, and its domain is never used to match duplicates, because two businesses on one platform have nothing to do with each other. Such a record can still match on its phone, or on its name and city.
How the score works
Add up the lines that apply, then keep the total between 0 and 100. There is nothing else in it, so the same checks always give the same score.
| Check | Points |
|---|---|
Website live | +40 |
Website redirected | +20 |
Website unknown | +15 |
Website parked, dead or no_website | 0 |
| Phone valid | +30 |
| Domain has mail servers | +20 |
| Mail server lookup failed | +10 |
| Has a company name | +10 |
| Duplicate of an earlier record | -30 |
A full 100 means a live website, a valid phone, mail servers and a name, with no duplicate.
Run it after a scraper
This Actor is built to be the next step after a scraper, for example a Google Maps scraper. To chain it, open the scraper's Integrations tab, choose Add integration, pick this Actor, and make sure its Dataset field points to the dataset of the run that triggered it (the integration variable resource.defaultDatasetId, in double curly braces). If the Dataset field is empty the run cannot read that dataset: it stops with a message and no record is charged.
This is an independent tool. It is not made or endorsed by Apify, by Google, or by the author of any scraper it runs after.
Which fields are read
Names are matched ignoring case, spaces, underscores and hyphens, so Company Name and company_name are the same. Fields inside an object are read only from company, business, organization, organisation and contactInfo, and from contact if it holds no name or email. Nothing is read from an object with a person's name in it.
- Name:
company,companyName,businessName,employer,currentCompany,name,organization,firm,accountNameand similar.titleis used only if a record has none of these and looks like a place listing, with anaddress,street,placeIdorcategoryName, because in other lists it holds a job title. A company name inside an object is read only from the first four objects above. - Website:
website,homepage,web,webAddress,webpage,site,companyWebsite,companyDomain,domainand similar.urlandlinkare used only if a record has no website field at all, and only for a homepage off the shared platforms: in Google Maps outputurlis a Maps link. - Phone:
phoneUnformatted,phone,phoneNumber,telephone,tel,mainPhone,phone1,phonesand similar.mobileandcellare used only if a record has no such field. A row that looks like a person's gets no phone check at all: one with a first, last or contact name, an owner, a manager, a director, or a job title such as CEO beside a company. Blank columns do not count, andreasonssays when a phone was left unchecked. This is a pattern match on column names, so it cannot catch every case. Use this Actor on company lists, not lists of people. - City:
city,town,locality. Country:countryCode,country.
The run log lists which field fed each check. If no website field and no phone field can be found in the first 500 records, the run stops before charging for any record and asks for fieldMapping. A mapping for either one lets the run go on, and if a mapped field is not in those records the log warns.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
datasetId | string | no | - | The dataset of leads to verify. To chain this Actor after another run, point it at that run's dataset. |
records | array | no | [] | Leads pasted as a JSON list of objects, verified after the dataset. Each needs at least a name, website or phone field. |
defaultCountry | string | no | empty | Two-letter country code for phones that have no country code and whose record has no country. |
fieldMapping | object | no | {} | Only when detection misses a field: maps name, website, phone, city and country to your top-level field names. |
An empty run returns a small sample.
Pricing
Pay-Per-Event:
| Event | Price |
|---|---|
lead-verified | $1.50 per 1,000 records ($0.0015 each) |
apify-actor-start | $0.00005 per run |
A record with an unknown website, or with a website value that is not a web address, still counts: its other fields were checked.
These records are not charged, and the FAILED_ITEMS record of the run's key-value store lists each one with a reason: an entry that is not an object, one with no name, website or phone, and one whose website is on a private or internal address. FAILED_ITEMS holds count, items (the first 10,000) and processed, the number of input records handled.
A run that reaches your spending limit stops there. The records after that point are not checked, not charged and not listed anywhere, and the log and status message say the run stopped.
Sample output
{"name": "NASA Goddard","website": "https://www.nasa.gov/goddard/","phone": "(301) 286-2000","city": "Greenbelt","countryCode": "US","verification": {"index": 1,"phone": {"e164": "+13012862000","valid": true,"lineType": "fixed_line_or_mobile"},"domain": "nasa.gov","websiteStatus": "live","finalUrl": null,"mx": true,"duplicateOf": 0,"score": 70,"reasons": ["+40 website is live","+30 phone is valid","+20 domain has mail servers","+10 has a company name","-30 duplicate of record 0 (same domain)"],"checkedAt": "2026-11-05T17:26:22.097Z"}}
Integrations
Chain it from a scraper's Integrations tab as described above, call it from n8n, Make or Zapier, or use the Apify API:
curl -X POST "https://api.apify.com/v2/acts/VERRR~lead-list-verifier/runs?token=<YOUR_TOKEN>" \-H "Content-Type: application/json" \-d '{ "datasetId": "<dataset-id>" }'
Use cases
- Clean a Google Maps lead list before it reaches your CRM: drop dead and parked businesses, and merge duplicates.
- Verify phone numbers in bulk and normalise them to E.164 for a dialler.
- Check websites in bulk for live, parked, redirected and dead domains.
- Sort any scraped lead list by a quality score, with the reason for each score.
Limits and FAQ
- Does it check email addresses? No. It asks DNS whether the company's domain has mail servers. It does not validate, find or look up any mailbox, it looks up nothing about people, and it adds no personal data. Other fields of your own records pass through untouched.
- Does a valid phone mean someone will answer? No.
validandlineTypecome from each country's numbering plan, with no carrier lookup. The number fits the plan, but the line may be out of service. In the US and Canada the plan cannot tell mobile from landline, so most numbers readfixed_line_or_mobile. - Why is a phone not valid when it looks fine? A number with no country code needs a country. Add one to the record or set
defaultCountry. Thereasonslist says when this is the cause. - Why are all branches of a chain marked as duplicates? They share a domain, so each points at the first branch. If you want every branch, ignore
duplicateOfand add 30 back to the score. - Is the same site checked again for every row? No. Each host is checked once per run, one request at a time, and each domain's mail servers once, however many rows share them.
- Which page is checked? The homepage on the standard ports, never the path or port in your record. JavaScript and meta refresh redirects are not followed, so such a site reads
live. - Do you find every parked domain? No. Parking pages change, and the page wording we read is English only. Parking name servers, known marketplaces and parking networks' code work in any language.
- Is every shared platform known? No. There is one hand-kept list of social sites, directories, booking platforms, free hosts, site builders and free mail domains, and it grows. Everything else counts as an own website, so rows on a platform we do not list yet are checked as sites, and two of them can match as duplicates by domain.
- How big can a run be? The largest runs tested so far had 50,000 records, with the network stubbed out: 76 seconds and 271 MB on 200 domains, 174 seconds and 690 MB on 50,000 domains. Real sites take longer. A run stops by itself at 500,000 records, which is a safety limit and not a tested size.
- Do I need a proxy? No, and none is used. Each site's robots.txt and crawl delay are obeyed.
- Is it monitored? Yes. A sample run is checked weekly.
Legal note
This Actor reads public DNS records and public homepages for the targets you supply, and adds no personal data. Your records may hold personal data of their own: they pass through unchanged, and you are responsible for using them, and the output, in line with applicable laws and each site's terms.