Request a tool
All toolsAutomationsGuidesMCP serverRequest a toolPlatformsCategories
Phone Number Validator icon

Phone Number Validator

Validate phone numbers in bulk, offline. Get E.164 and national formats, country, mobile or landline, region, original carrier and time zones for each number.

42 runs on Apify $0.00026 per number checked ($0.26 / 1,000)
Run this in the cloudRun on Apify →

Developer & Research Tools

How it works

  1. 1
    Open it on Apify

    Hit Run on Apify — it opens the tool in the cloud, no install.

  2. 2
    Set the inputs

    Adjust phoneNumbers, defaultCountry, datasetId (sensible defaults are pre-filled).

  3. 3
    Click Run

    The tool runs on Apify’s cloud and collects the data for you.

  4. 4
    Export the results

    Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.

Pricing

$0.00026 per number checked = $0.26 per 1,000

You are charged forWhenPrice
Number checkedOne distinct phone number checked and returned in the dataset, valid or not. Blank entries and repeats in the same run are never charged.$0.00026

Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-09-14, and they are what you are actually charged.

Inputs

FieldWhat it doesType
phoneNumbersOne number per line, written any way: +44 20 7946 0018, (201) 555-0123, 0033 6 12 34 56 78 or tel:+81-3-1234-5678. Numbers without + or 00 in front need the default country below. Leave this empty to check a dataset instead.array
defaultCountryThe country for numbers written without + or 00, the way people write local numbers. (201) 555-0123 checks out as a US number with United States here and fails with most other countries. Numbers that start with + or 00 carry their own country and ignore this.string
datasetIdCheck the numbers in one of your Apify datasets, for example the results of a business-listing or lead scraper. Pick it here, or pass its ID as datasetId through the API. Works together with the list above.string
datasetFieldThe field in each dataset item that holds the number: phone unless you change it. Use dots for a nested field (contact.phone). A field holding a list checks every number in it.string
addRegionAndCarrierFor valid numbers, add the place the number range belongs to (for landlines usually a town or city), the carrier the range was first given to, and its time zones. Switch it off for just the check and the formats.boolean
languageNames that don't exist in the chosen language come in English.string
onlyValidReturn only the numbers that pass the check. The others are left out and aren't charged.boolean
numberTypesReturn only valid numbers of these types, mobile for example. Leave it empty for every type. Numbers left out aren't charged. In the US and Canada most numbers come back as "landline or mobile", so pick that too for those.array
countriesReturn only numbers that belong to these countries. Leave it empty for every country. Numbers left out aren't charged.array
maxNumbersThe most numbers checked in one run. Only distinct, non-blank entries count, and each one checked is charged.integer

What you get

A structured dataset — each result includes fields like:

inputvalidreasone164nationalcountrynumberTypesmsCapableregioncarriertimeZones

Export every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.

Related tools in Developer & Research Tools

Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.

GitHub Scraper iconDeveloper & Research Tools

GitHub Scraper

Search GitHub repos and users: stars, forks, language, topics, licence, plus user bio, company and followers. No token needed. $0.90 per 1,000 rows.

18 use cases

Stack Overflow / Stack Exchange Scraper iconDeveloper & Research Tools

Stack Overflow / Stack Exchange Scraper

Search Stack Overflow and Stack Exchange by keyword or tag. Score, answer count, views, reputation and body text. $2 per 1,000 questions.

2 use cases

Package Registry Scraper (npm + PyPI) iconDeveloper & Research Tools

Package Registry Scraper (npm + PyPI)

Get npm and PyPI package metadata as JSON. Version, license, author, repo, keywords and npm monthly downloads. $2 per 1,000 packages.

2 use cases

arXiv Scraper iconDeveloper & Research Tools

arXiv Scraper

Search arXiv papers by title, author, abstract or category. Get full abstracts, authors, categories, DOI, dates and PDF links. $2 per 1,000 papers.

2 use cases

OpenAlex Scholarly Works Scraper iconDeveloper & Research Tools

OpenAlex Scholarly Works Scraper

Search 250M+ OpenAlex papers with no API key. Get titles, authors, venue, year, citations, DOI, OA links and full abstracts. $2.00 per 1,000 papers.

2 use cases

Crossref Scholarly Works Scraper iconDeveloper & Research Tools

Crossref Scholarly Works Scraper

Search 150M+ papers on Crossref: DOI, title, authors, journal, publisher, date, citations and abstract. No API key. $1.00 per 1,000 works.

2 use cases

See all Developer & Research Tools →

Phone Number Validator

Paste phone numbers, or point it at a dataset of leads, and get one row for each number. The row tells you whether the number is valid and, if not, why. It gives the number in E.164, international and national form, the country, and what kind of line it is: mobile, landline, toll-free, VoIP and so on. Valid numbers also get the place their number range belongs to, the carrier the range was first given to, and the time zones it covers.

Everything happens inside the run. No number is called, texted or looked up on a phone network, and nobody on your list notices anything.

What it doesn't do

  • It can't tell you whether a number is switched on right now. Valid means the number fits a range the country actually uses. It may still be disconnected, or never handed out. Only a live lookup through a phone network can tell that, and this doesn't do one.
  • It doesn't say who owns a number. No names, no addresses.
  • The carrier is the original one. People keep their number when they change carrier, so for a moved number the carrier column shows the old one.
  • In the US and Canada, mobiles and landlines share the same ranges, so numbers there come back as "landline or mobile". Most other countries keep the two apart.
  • No WhatsApp or Telegram check.

Input

Phone numbers. One per line, written any way you like: +44 20 7946 0018, (201) 555-0123, 0033 6 12 34 56 78, tel:+81-3-1234-5678. An extension such as ext. 12 goes into its own column.

Default country. A local number, one without + or 00 in front, only means something with a country. (201) 555-0123 checks out as a US number when this is set to United States, and fails with most other countries. Pick the country your list mostly comes from. Numbers that start with + or 00 carry their own country and ignore this setting.

Dataset and field. To check the results of another actor, a business-listing scraper say, pick its dataset (or pass the ID as datasetId through the API) and give the name of the field that holds the number (phone unless you change it). The actor can read only the dataset you pick, and it never writes to it. Nested fields work with dots, such as contact.phone, and a field holding a list checks every number in it. A dataset and a pasted list can go in the same run.

Add region, carrier and time zones. On by default. Switch it off if you only want the check and the formats.

Language for region and carrier names. English by default, with 32 other languages. A name that doesn't exist in the chosen language comes in English.

Filters. Three optional ones. *Only valid numbers* drops the ones that fail the check. *Only these line types* keeps, say, just mobiles; it leaves out invalid numbers too, since those have no type. *Only these countries* keeps numbers from the countries you pick. A number the filters leave out isn't returned and isn't charged. In the US and Canada most numbers come back as "landline or mobile", so when you filter for mobiles there, pick that type as well.

Maximum numbers. 10,000 unless you change it, and up to 500,000 in one run. Only distinct, non-blank numbers that pass your filters count.

Output

One row per distinct number, in the order they came in.

FieldExampleNotes
input(201) 555-0123as you wrote it
validtrue
possibletruethe length is right for the country, even when the number itself isn't in use
reasonwrong length for Francewhy it isn't valid; empty when it is
e164+12015550123the form most systems want
international+1 201 555 0123
national(201) 555-0123how people dial it inside the country
rfc3966tel:+12015550123the form links and contact cards use
extension12when the entry had one
countryCodeUStwo-letter code
countryUnited States
callingCode+1
numberTypelandline or mobileone of: mobile, landline, landline or mobile, toll-free, premium rate, shared cost, VoIP, personal number, pager, UAN, voicemail
smsCapabletruetrue for mobiles, false for landlines and special numbers, empty when the numbering plan can't tell (landline or mobile, VoIP)
regionMountain View, CAwhere the number range belongs
carrierThreethe carrier the range was first given to
timeZones["America/Los_Angeles"]
source, sourceIndexlist, 2the line of your list, or the position of the item in your dataset

For a landline, region is usually a town or city. Many countries don't tie mobile ranges to a place, so for mobiles it is often empty. A number that isn't tied to one place, such as a US toll-free number, lists every time zone in its country.

When a number isn't valid, reason says why in plain words: too short, wrong length for France, not a number in use in Germany, unknown country code or no country code: start it with + or set a default country. The formatted columns stay empty for those, so an invalid number can't slip into a column you import somewhere else.

The run also writes a report, RUN_REPORT in the key-value store, with counts by verdict, reason, type and country, and a note of what was skipped.

What you pay

Each distinct number checked is one charge, valid or not, because the verdict is what you asked for. Blank entries and repeats of a number already checked in the same run are skipped and never charged. 020 7946 0018 with United Kingdom set and +44 20 7946 0018 count as the same number. If you set a maximum charge for the run, it stops when that is reached, and every row you get has been paid for. The price itself is on the Pricing tab.

Where the rules come from

Validity, line types and formats come from libphonenumber-js, which follows Google's libphonenumber numbering plans; this build uses version 1.13.13, released in September 2026. Region, carrier and time-zone names come from the tables in libphonenumber-geo-carrier 2.0.0, built from the same Google data. Countries open new number ranges from time to time, so a range that went live after this build can show up as "not a number in use" until the actor is updated.

Questions

Why is a number I know works marked "not a number in use"? Either its range is newer than the data, or it was read with the wrong country. Check the default country, or write the number with + and its country code.

Does it change my dataset? No. It only reads the field you name, and writes its own results to its own dataset.

Can it tell me which numbers take text messages? As far as the numbering plan goes, yes: smsCapable is true for mobiles and false for landlines and special numbers. It's empty where the plan can't tell, as with "landline or mobile" numbers in the US and Canada and with VoIP. Whether a mobile is switched on right now needs the live lookup this actor doesn't do.