Phone Number Validator: Format, Type, Country & Carrier
Pricing
$0.20 / 1,000 number checkeds
Phone Number Validator: Format, Type, Country & Carrier
Validate and format phone numbers in bulk, offline. E.164, international and national formats, mobile or landline, country, original carrier, city and time zone for up to 1,000,000 numbers per run. Finds numbers in pasted text. $0.20 per 1,000.
Pricing
$0.20 / 1,000 number checkeds
Rating
0.0
(0)
Developer
Michael Shanker
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Security
Limited permissionsShare
Clean a phone number list in one run. Give it numbers in any format ((202) 456-1414, +44 20 7219 3000, 0049 30 227-0, 1-800-FLOWERS) and get one row per number back: valid or not, E.164 and other standard formats, mobile or landline, country, city or area, original carrier and time zone. Up to 1,000,000 numbers per run for $0.20 per 1,000.
It works fully offline. Every check uses the numbering-plan data inside phonenumbers, the Python port of Google's libphonenumber (the library Android and Google use to read phone numbers, Apache-2.0). No website or API is called, so runs are fast, cheap and never rate limited, and your numbers never leave the run.
Who it's for
- CRM and marketing teams cleaning a contact list before an import or an SMS campaign: drop invalid numbers, split mobiles from landlines, store everything in E.164.
- Developers who need E.164 for Twilio, WhatsApp Business or a database column, without adding a library to their own code.
- Lead and data teams who scraped or bought a list and want to know which numbers can be real, from which country, and in which time zone to call.
- Anyone with a pile of text (emails, notes, web page text): turn on Find numbers in text and it pulls out every phone number.
What it does and doesn't do
| This tool | Live lookup tools (HLR or carrier APIs) | WhatsApp checkers | |
|---|---|---|---|
| Valid number for its country, possible length | Yes | Yes | Some |
E.164, international, national, tel: formats | Yes | Varies | No |
| Mobile, landline, toll free, VoIP, premium... | Yes, from the number range | Yes | No |
| Country, city or area, time zones | Yes | Country, sometimes more | No |
| Carrier | Original carrier of the number range (no porting) | Current carrier | No |
| Is the line switched on right now / has WhatsApp | No | Yes (line status) | Yes (needs a logged-in account) |
| Speed and price | Thousands per second, $0.20 per 1,000 | Slower (one network query per number), usually priced higher | Slow, one number at a time |
So use this to format, validate and classify numbers cheaply, and use a live lookup only for the numbers where you need to know the line is active today.
Input
| Field | What it does |
|---|---|
| Phone numbers | One per line, any common format. Letters on vanity numbers are converted (1-800-FLOWERS). Extensions are read (ext. 123, x123). |
| Default country | Two-letter code (US, GB, DE, IN...) for numbers written without a + country code. Without it, such numbers come back as unparseable with the reason missing_country (free). UK is accepted for GB. International dialing prefixes are read for this country (011 for US, 00 for most of Europe). |
| Text | Paste numbers here instead, one per line (commas, semicolons and tabs also separate them), e.g. a column copied from a spreadsheet. |
| Find numbers in text | Read Text as free text and extract every valid phone number in it. Each row gets the matched text (input) and where it starts (textOffset). Dates, order numbers and invalid numbers are skipped. Numbers without + are found only when valid for the default country. |
| Numbers with their own country (JSON) | For mixed lists: [{"number": "020 7219 3000", "country": "GB"}, {"number": "030 227-0", "country": "DE"}]. The country overrides the default for that number. |
| Remove repeats | On by default. Each number is checked once per run by its E.164 form, so +1 202-456-1111 and (202) 456-1111 count as one. Repeats are skipped and not charged. |
Example input:
{"numbers": ["+1 202-456-1111", "(202) 456-1414", "+44 20 7219 3000", "1-800-FLOWERS", "202-555-01", "not a number"],"defaultCountry": "US","dedupe": true}
Output
One row per number, in this shape (a UK mobile from libphonenumber's own example range):
{"position": 4,"source": "numbers","input": "+44 7400 123456","countryHint": "US","status": "valid","valid": true,"possible": true,"notPossibleReason": null,"e164": "+447400123456","international": "+44 7400 123456","national": "07400 123456","rfc3966": "tel:+44-7400-123456","countryCode": 44,"region": "GB","countryName": "United Kingdom","numberType": "mobile","originalCarrier": "Three","location": null,"timeZones": ["Europe/Guernsey", "Europe/Isle_of_Man", "Europe/Jersey", "Europe/London"],"extension": null,"error": null}
status:valid(a real, assigned number range for that country),invalid(parsed, but not a valid number: wrong length or an unused range), orunparseable(not a phone number at all, or the country can't be known;errorsays why). Onlyvalidandinvalidare charged.possible/notPossibleReason: whether the length could work at all. Reasons:too_short,too_long,invalid_length,invalid_country_code, and for unparseable input alsonot_a_numberandmissing_country. A number can be possible but still invalid (right length, unused range).numberType:mobile,fixed_line,fixed_line_or_mobile(the US, Canada and a few others don't separate them),toll_free,premium_rate,shared_cost,voip,personal_number,pager,uan,voicemail, orunknown.originalCarrier: the operator the number range was originally allocated to, when the library knows it (mostly mobiles). Numbers may since have been ported to another operator, so this is not necessarily today's carrier. Many countries (including the US and Canada) have no carrier data.location: city, area or state in English for geographic numbers (London,Washington D.C.,Berlin);nullfor mobiles and non-geographic numbers, or when only the country is known.regionis the ISO country code;nullfor global numbers such as+800international freephone.positionis the place in your input (1 = first);sourcesays which field it came from. Rows from the same batch can be saved slightly out of order, so sort bypositionif order matters.- For
invalidnumbers the formats show how the digits read with that country code; filter onvalidbefore dialing.
Download results as JSON, CSV or Excel, or send them to Google Sheets, Zapier, Make or n8n. The run also saves a SUMMARY record: counts of valid, invalid, unparseable and repeats, numbers per type and per country, numbers charged, speed, and whether the spending cap stopped the run.
Pricing
Pay per event: $0.0002 per number checked ($0.20 per 1,000). You pay for every number that parsed, valid or invalid, because that verdict is the result. Text that isn't a phone number (no digits, garbage, an unknown + code, a national number with no country to read it by) is saved with the reason for free, and repeats skipped by Remove repeats are free too. No start fee. Set a maximum charge per run in the run options and the Actor stops cleanly when it's reached (checked before every batch of 500 numbers).
Speed and memory
- About 14,000 numbers per second on one full CPU core (measured locally on 1,000,000 generated numbers from 20 countries, dataset writes not counted).
- Apify gives an Actor CPU in proportion to its memory (a full core per 4 GB). At the default 256 MB expect roughly 1,000 numbers per second, so a million numbers take around 20 minutes. Give the run 1 to 4 GB to go several times faster; the price per number stays the same.
- 1,000,000 numbers sent as plain text peaked at about 200 MB of memory locally, so the 256 MB default is enough. If you send hundreds of thousands of numbers as
{"number", "country"}objects, use 512 MB, because each object takes more memory to read. - Very large lists make a large input. If the Console refuses to save it, split the list over a few runs or start the run through the API.
Good to know
- Valid doesn't mean in service.
validmeans the number belongs to a range the country's numbering plan has assigned. It can't tell whether a particular line is connected, who owns it, or whether it has WhatsApp. That needs a live network lookup, which this tool deliberately doesn't do. - Data freshness. Numbering plans change. The data is as fresh as the phonenumbers release in the build (the version is in
SUMMARY.phonenumbersVersion); rebuilding the Actor picks up new releases. - No web requests at all. There's nothing to rate limit and no robots.txt to respect, because nothing is fetched. Your numbers are only processed inside the run and stored in your own dataset.
- Your data, your responsibility. Phone numbers of people are personal data. Validate only lists you're allowed to process, and follow the rules that apply to you (for example GDPR, TCPA and do-not-call rules) before you call or text anyone.
This Actor isn't affiliated with or endorsed by Google, the libphonenumber project or any telephone operator.