Lead List Verifier: Phone, Website, MX, Duplicates avatar

Lead List Verifier: Phone, Website, MX, Duplicates

Pricing

from $1.50 / 1,000 lead verifieds

Go to Apify Store
Lead List Verifier: Phone, Website, MX, Duplicates

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

VER RR

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Security

Limited permissions

Share

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) and lineType (such as mobile, fixed_line, fixed_line_or_mobile, toll_free, voip, or null when not known).
  • verification.domain: the canonical registrable domain, such as acme.co.uk for https://www.acme.co.uk/shop. Null when the record has no own website.
  • verification.websiteStatus: live, redirected, parked, dead, no_website or unknown.
  • 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: the index of 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

StatusMeaning
liveThe 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.
redirectedThe site sends visitors to another domain. finalUrl shows where.
parkedParking 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.
deadThere is proof: the domain has no address in DNS, or every route to it answers 404 or 410.
no_websiteThe 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.
unknownWe 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.

CheckPoints
Website live+40
Website redirected+20
Website unknown+15
Website parked, dead or no_website0
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, accountName and similar. title is used only if a record has none of these and looks like a place listing, with an address, street, placeId or categoryName, 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, domain and similar. url and link are used only if a record has no website field at all, and only for a homepage off the shared platforms: in Google Maps output url is a Maps link.
  • Phone: phoneUnformatted, phone, phoneNumber, telephone, tel, mainPhone, phone1, phones and similar. mobile and cell are 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, and reasons says 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

ParameterTypeRequiredDefaultDescription
datasetIdstringno-The dataset of leads to verify. To chain this Actor after another run, point it at that run's dataset.
recordsarrayno[]Leads pasted as a JSON list of objects, verified after the dataset. Each needs at least a name, website or phone field.
defaultCountrystringnoemptyTwo-letter country code for phones that have no country code and whose record has no country.
fieldMappingobjectno{}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:

EventPrice
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. valid and lineType come 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 read fixed_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. The reasons list 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 duplicateOf and 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.

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.