Phone Number Validator & Formatter – Bulk, Carrier, Line Type
Pricing
from $5.00 / 1,000 phone number validateds
Phone Number Validator & Formatter – Bulk, Carrier, Line Type
Validate and format phone numbers in bulk for 240+ countries: valid/possible, E.164, international and national formats, mobile/fixed/VoIP/toll-free type, original carrier, location and time zones. Offline Google libphonenumber - fast and cheap, 100k numbers per run.
Pricing
from $5.00 / 1,000 phone number validateds
Rating
0.0
(0)
Developer
Cemal Atakli
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
11 hours ago
Last modified
Categories
Share
Phone Number Validator & Formatter – Bulk, 240+ Countries, Carrier & Line Type
Validate, clean and format phone numbers in bulk. Paste a list, upload a CSV or point the Actor at another Actor's dataset. For each number you get:
- valid / possible plus a plain-English reason when a number is invalid (too short, too long, unknown country code, unallocated range, missing area code)
- E.164 (
+14155550123), international, national and RFC 3966 (tel:) formats - country calling code, ISO country (US, GB, DE…) and country name
- line type: mobile, fixed line, fixed_line_or_mobile, VoIP, toll-free, premium rate, shared cost, UAN, pager, personal number or voicemail
- original carrier (for mobile ranges), location (city or region) and time zones
- the extension, if the input had one
It is built on Google's libphonenumber, the library Android, Google and most CRMs use, and covers 240+ countries and territories. All checks run offline, which makes the Actor very fast: 100,000 numbers in about a minute, at $5 per 1,000 numbers.
What it does NOT do (please read)
- No live network lookup (HLR / ping / SMS). A number can be correctly formatted and in an allocated range and still be disconnected or unused. The Actor tells you whether a number can exist, not whether someone answers it.
- The carrier is the carrier the number range was originally allocated to. Numbers that were ported to another operator still show the original carrier. Many countries (the US and Canada among them) don't publish carrier data per range, so
carrieris empty there. - In the US and Canada most numbers are reported as
fixed_line_or_mobile, because the numbering plan does not separate mobile and landline ranges.
Use cases
- CRM and lead-list cleanup: normalise every phone to E.164 before you import into HubSpot, Salesforce, Pipedrive or Zoho, and drop the invalid ones.
- SMS and WhatsApp campaigns: keep only
mobilenumbers and skip landlines and toll-free numbers, so you don't pay for messages that can't be delivered. - Scraped data enrichment: validate the
phonefield from Google Maps, Yelp or contact-scraper datasets in one run withdatasetId. - Form and signup QA: find fake numbers such as
555-0123, too-short entries and unknown country codes. - Call scheduling: use
timeZonesto call people during their business hours. - AI agents: give an LLM a deterministic tool for "is this a real phone format, and what is it in E.164?"
Input
You can combine the sources below. Numbers can be written in any format: spaces, dashes, dots, brackets, (0), 00 or 011 prefixes, tel: links, ext. / x extensions, vanity letters (1-800-FLOWERS) and full-width digits all work.
| Field | What it does |
|---|---|
phoneNumbers | List of numbers |
defaultCountry | ISO code (US, GB, DE, IN, BR, TR…) used for numbers written without +/00 |
bulkText | Paste one number per line or a whole CSV/TSV with a header row |
sourceFileUrl | URL of a CSV/TXT file, for example a Google Sheets "Publish to web" CSV |
datasetId | An Apify dataset ID or name. The phone field is auto-detected, and list fields such as phones: [...] are expanded |
phoneColumn, countryColumn | Set these when auto-detection picks the wrong column. The country column sets the country per row |
keepFields | Columns to copy into each result (for example id, email) so you can join the results back to your data |
dedupe | Removes duplicates, compared in E.164 (on by default; duplicates are not charged) |
outputFilter | all, valid or invalid. Hidden rows are not charged |
includeCarrier, includeLocation, includeTimeZones, language | Choose the enrichment fields and the language for names |
assumeInternational | When no country is known, read a bare 4915123456789 as +49… (flagged as parsedAs: "assumed_international") |
maxNumbers | Cap for test runs |
{"phoneNumbers": ["+1 650-253-0000", "(201) 555-0123", "1-800-FLOWERS", "+44 20 7946 0958 ext. 12", "0049 30 2270", "+90 532 123 45 67"],"defaultCountry": "US","dedupe": true}
Output
One dataset row per number. The Overview table shows the key columns, and Why invalid lists the rejected numbers with their reasons. The full output can be exported as JSON, CSV or Excel.
{"input": "+90 532 123 45 67","valid": true,"possible": true,"reason": null,"reasonCode": null,"e164": "+905321234567","international": "+90 532 123 45 67","national": "0532 123 45 67","rfc3966": "tel:+90-532-123-45-67","countryCallingCode": 90,"nationalNumber": "5321234567","extension": null,"regionCode": "TR","countryName": "Turkey","numberType": "mobile","carrier": "Turkcell","location": "Turkey","timeZones": ["Europe/Istanbul"],"defaultCountry": "US","parsedAs": "international","source": "phoneNumbers","rowNumber": 12}
An invalid number keeps whatever the Actor could still work out:
{ "input": "+44 7700 900123", "valid": false, "possible": true, "reasonCode": "INVALID_RANGE","reason": "Right length, but not in any allocated number range for GB", "e164": "+447700900123", "regionCode": "GB" }
reasonCode values: NOT_A_NUMBER, INVALID_COUNTRY_CODE, TOO_SHORT, TOO_LONG, INVALID_LENGTH, LOCAL_ONLY (the area code is missing), INVALID_RANGE.
Pricing
Pay per event: $0.005 per number validated ($5 per 1,000), plus a tiny start fee ($0.0001). Blank cells, values without any digits, removed duplicates and rows hidden by the output filter are not charged. Set a Maximum cost per run and the Actor stops cleanly when it reaches it.
| Actor | Price per 1,000 numbers |
|---|---|
| khadinakbar/phone-number-lookup-api | $25 |
| checkthatphone/phone-validator (US carrier/TCPA lookup, a different service) | $15 |
| This Actor | $5 |
Competitor prices are from the Apify Store in September 2026 and may change.
FAQ
Is a "valid" number guaranteed to be in service? No. "Valid" means the number is in a range the country's numbering plan has allocated. Only a live HLR lookup, which this Actor does not do, can tell you whether a SIM is active.
Why is carrier empty? Carrier data only exists for mobile ranges in countries that publish it. The US, Canada and a few others don't. Ported numbers keep the original carrier name.
What default country should I use? The country most of your numbers come from. Numbers with + or 00 are always read as international. If your CSV has a country column, it overrides the default for each row.
How big can a run be? 100k+ numbers per run works well with the default 512 MB. Results are written in chunks of 1,000.
Is my data sent anywhere? No. Validation runs inside the Actor with no third-party calls. The only network requests are for the file URL or dataset you give it.
Which data source is used? libphonenumber by Google (Apache 2.0), through the Python port phonenumbers. Updates to the metadata ship with new Actor builds.
Use with AI agents / Apify MCP
The Actor is deterministic, fast and cheap, which makes it a good tool for AI agents. Add it to Claude, Cursor or any MCP client through the Apify MCP server (https://mcp.apify.com?actors=gazidev/phone-validator) and ask, for example, "Normalise these 50 phone numbers to E.164 and tell me which ones are mobile". You can also call it over the API:
curl -X POST "https://api.apify.com/v2/acts/gazidev~phone-validator/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"phoneNumbers":["+1 650-253-0000","030 2270"],"defaultCountry":"DE"}'
Other Actors by gazidev
Scraped contact data? Pair this Actor with our website contact and tech-stack tools to build clean, enriched lead lists.