Phone Number Validator - Bulk Format, Type & Carrier avatar

Phone Number Validator - Bulk Format, Type & Carrier

Pricing

from $0.25 / 1,000 numbers

Go to Apify Store
Phone Number Validator - Bulk Format, Type & Carrier

Phone Number Validator - Bulk Format, Type & Carrier

Validate phone numbers in bulk: valid or not and why, mobile or landline, country, and E.164, international and national forms. Valid numbers also get region, original carrier and time zones. Paste a list or check a dataset field. Nobody is called. $0.26 per 1,000 numbers.

Pricing

from $0.25 / 1,000 numbers

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

18 hours ago

Last modified

Share

Validate phone numbers in bulk: valid or not, line type, carrier and clean E.164 format: paste a list of numbers, or point it at a field in one of your own Apify datasets. Every distinct number comes back as a row: valid or not and why not, the E.164, international, national and tel: forms, the country, the calling code, and whether it is a mobile or a landline.

Nobody is called and nothing is texted. This is a check against the world's numbering plans, so it tells you whether a number can be right at all, not whether it is switched on today.

InputA list of numbers, a field in one of your datasets, or both
OutputOne row per distinct number: verdict and reason, E.164 and other formats, country, line type, region, carrier, time zones
Ceiling500,000 numbers per run
SpeedA few seconds for a short list; 100,000 numbers took 93 to 139 seconds on measured runs
Account neededNone
Price$0.26 per 1,000 numbers checked, flat on every plan. The free plan's $5 a month covers about 19,000

🔍 What Phone Number Validator does

Write the numbers however you have them. +44 20 7946 0018, (201) 555-0123, 0033 6 12 34 56 78 and tel:+81-3-1234-5678 all parse. A leading 00 becomes +, a tel: prefix is dropped, and spaces, brackets and dashes do not matter.

A number without + or 00 has no country in it, so the run uses your Default country to read it. (201) 555-0123 is a valid United States number and is nonsense as a French one, which is the whole reason that field exists.

For the numbers that pass, you also get the region the range belongs to, which for a landline is usually a town or city, the carrier the range was first handed to, and the time zones it covers. Region and carrier names come back in any of 33 languages.

The datasetId field is the part that saves real work. Point it at the output of a business-listing scraper, name the field that holds the number, and the two run back to back without you exporting anything.

📋 What data you get from each phone number

What you getField
Whether it passes, and why not when it does notvalid, possible, reason
The number in E.164, international, national and tel: form, plus any extensione164, international, national, rfc3966, extension
The country, its code and the calling codecountry, countryCode, callingCode
Mobile, landline and the other line types, and whether it takes textsnumberType, smsCapable
The place the range belongs to, its original carrier and its time zonesregion, carrier, timeZones
What you sent, and where it came from in your list or datasetinput, source, sourceIndex

▶️ How to validate phone numbers in bulk

  1. Open Phone Number Validator and click Try for free.
  2. Paste numbers into Phone numbers, or pick a dataset under Dataset and name the field.
  3. Set Default country if your list has local numbers in it.
  4. Add filters under Only valid numbers, Only these line types or Only these countries.
  5. Click Start, then download the dataset as JSON, CSV or Excel, or read it from the Apify API.

Start it with nothing to check and you get one free sample row showing the output shape.

💰 How much does it cost to validate phone numbers?

$0.26 per 1,000 numbers checked. The same rate on every Apify plan, with no volume tiers. On the free plan, the $5 Apify gives you each month covers about 19,000 numbers.

One charge per row delivered. Blanks, repeats of a number already in the run, and anything your filters remove are not charged, and neither is the sample row. Region, carrier and time zones cost nothing extra.

📥 What you give it

{
"phoneNumbers": ["+44 20 7946 0018", "(201) 555-0123", "06 12 34 56 78"],
"defaultCountry": "US",
"onlyValid": true,
"numberTypes": ["mobile"],
"maxNumbers": 5000
}
FieldDefaultWhat it is
phoneNumbersnoneOne per line, up to 500,000. Leave it empty to check a dataset instead. The form starts with four examples, which are a prefill.
defaultCountrynoneTwo-letter code, from a list of 245. Used only for numbers written without + or 00. The form starts on US, which is a prefill, not a default.
datasetIdnoneOne of your own datasets, picked from a list in the form or passed as an ID through the API. Works alongside the list.
datasetFieldphoneWhich field holds the number. Dots reach a nested one, like contact.phone. A field holding a list checks every number in it.
addRegionAndCarriertrueAdds region, carrier and time zones to valid numbers. Off leaves those three empty.
languageenFor region and carrier names, from 33 languages. Names missing in your language come back in English.
onlyValidfalseLeave out numbers that fail the check.
numberTypesnoneKeep only these line types: mobile, landline, landline or mobile, toll-free, VoIP and six more.
countriesnoneKeep only numbers belonging to these countries.
maxNumbers100001 to 500,000. Only distinct numbers that get past your filters count towards it.

Anything a filter leaves out is not charged, and neither are blanks or repeats. So onlyValid: true on a list that is half rubbish costs you roughly half.

In the United States and Canada, pick landline or mobile too if you are filtering by line type. Those two countries share number ranges between mobiles and landlines, so most numbers there honestly cannot be told apart and come back under that label.

📤 What you get back

Two real rows from a run on 3 October 2026 with the form's own example numbers: a London landline, which gets a region, and a French mobile, which gets a carrier.

[
{
"input": "+44 20 7946 0018",
"valid": true,
"possible": true,
"reason": null,
"e164": "+442079460018",
"international": "+44 20 7946 0018",
"national": "020 7946 0018",
"rfc3966": "tel:+442079460018",
"extension": null,
"countryCode": "GB",
"country": "United Kingdom",
"callingCode": "+44",
"numberType": "landline",
"smsCapable": false,
"region": "London",
"carrier": null,
"timeZones": ["Europe/London"],
"source": "list",
"sourceIndex": 1
},
{
"input": "+33 6 12 34 56 78",
"valid": true,
"possible": true,
"reason": null,
"e164": "+33612345678",
"international": "+33 6 12 34 56 78",
"national": "06 12 34 56 78",
"rfc3966": "tel:+33612345678",
"extension": null,
"countryCode": "FR",
"country": "France",
"callingCode": "+33",
"numberType": "mobile",
"smsCapable": true,
"region": null,
"carrier": "SFR",
"timeZones": ["Europe/Paris"],
"source": "list",
"sourceIndex": 3
}
]
FieldHow to read it
validThe number fits its country's numbering plan. This is the one to filter on.
possibleA length check only, set for anything that parses at all. A number can be possible and not valid.
reasonWhy a number failed, in plain words: "too short", "wrong length for France", "not a number in use in Germany", "unknown country code", "no country code: start it with + or set a default country". null when it passed.
carrierFilled for mobile ranges. A landline has a region instead.
smsCapabletrue for mobiles, false for landlines and other fixed types, null where the plan cannot say, which includes "landline or mobile" and VoIP.
sourceIndexThe line number in your list, or the item's offset in your dataset, so you can join the row back.

Formats, region, carrier and time zones are filled in only for numbers that pass. In the same run, 06 12 34 56 78 read with the US default came back valid: false with "not a number in use in United States", and nothing invented around it.

🧾 Reading the output

One row per distinct number, and that is the whole dataset. No refusal rows and no blank lines. A sample row carries _sample: true and turns up only when you run with nothing to check.

Everything else about the run is in a key-value record called RUN_REPORT:

In the reportWhat it tells you
Counts by verdict, reason, type and countryThe shape of your list in one place.
Entries skippedHow many were blank, how many were repeats, how many your filters removed.
The filters usedWritten out, including any value that was not recognised and dropped.
The dataset readItems seen, items with no number in the named field, and any error reading it.
Stop reason and seconds takenWhether it finished the list or hit maxNumbers, the deadline or your budget.

A run whose filters match nothing finishes normally and says so in the status message. A run with nothing to check at all fails.

💡 What people use it for

  • Cleaning a list of numbers down to the ones that can actually be dialled.
  • Splitting a list into mobiles and landlines.
  • Normalising a CRM export to E.164 so two systems finally agree on a format.
  • Working out which countries a list is really from, by counting countryCode.

From business listings to a checked list of numbers, in three runs:

  1. Run Yellow Pages US Scraper for the businesses you want.
  2. Here, pick that run's dataset under Dataset, leave the field as phone, set Default country to United States and tick Only valid numbers.
  3. Join the rows back to the listings on sourceIndex, which is each listing's position in that dataset.

🚧 What it does not do

  • It does not call or text anything. No answer test, no ring test, no HLR lookup. Nothing tells you whether a number is live, disconnected or answered today.
  • No names, no owners, no WhatsApp check.
  • carrier is the carrier the range was first given to. A ported number shows the old one. Take it as a hint about the range, not as fact about the handset.
  • United States and Canada numbers come back as "landline or mobile" most of the time, because the ranges are genuinely shared. smsCapable is null for those.
  • The numbering data has a date. A range that opened after the last update reads as not in use.
  • A number not tied to one place lists every time zone of its country. A US toll-free number names 42 of them.
  • 500,000 numbers in a run, and a large run wants the memory to match.
  • It is not an official tool of any platform or company named on this page. Dami's Studio is independent and is not affiliated with or endorsed by any of them.

🧭 Which list-cleaning tool do you need?

If you wantUse
Phone numbers checked and formattedThis one
Email addresses checkedEmail Verifier
Business listings with phone numbers to cleanGoogle Maps Scraper
US business listings with phone numbersYellow Pages US Scraper
Social profiles from a name or domainSocial Profile Finder

❓ Questions people ask

Does it ring the phone number?

No. Everything is worked out from the numbering plans, so nobody's phone lights up and nothing leaves the run.

Why did a number I know is fine come back invalid?

Nearly always a missing country. Set Default country to match where the local numbers were written, or put them in + form.

Can I call it from code or connect it to an AI assistant?

Yes. The API tab has ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/phone-number-validator. Either way the run happens on your Apify account at the same price.

Nothing is called or texted. A phone number is still personal data under GDPR and similar laws, so have a reason for holding the list. Apify's write-up on scraping and the law is a good start, and we are not lawyers.

🆘 If something breaks

Open the Issues tab on the actor page. Send the run ID and a number that came back wrong. The RUN_REPORT record in the run's key-value store carries the counts, the filters and the stop reason, which usually explains a short result on its own.