Phone Number Validator (libphonenumber) - Bulk E.164
Pricing
from $0.35 / 1,000 phone number validateds
Phone Number Validator (libphonenumber) - Bulk E.164
First 25 numbers free per run, then $0.50 per 1,000. Bulk phone enrichment: country, region, timezone, line type, validity, E.164, formats. Offline libphonenumber, no API key. Accepts phoneNumbers and defaultCountry inputs from other validators.
Pricing
from $0.35 / 1,000 phone number validateds
Rating
0.0
(0)
Developer
Penny Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
19 minutes ago
Last modified
Categories
Share
First 25 numbers per run are free; after that $0.50 per 1,000. Enrichment: country, region, timezone, line type (offline, no API key).
Phone Number Validator - Bulk E.164, Line Type & Format Check ($0.50 per 1,000)
Validate, parse and format phone numbers in bulk using Google's libphonenumber metadata (via libphonenumber-js). Blank or unparseable inputs are returned with an error code.
Try it free: turn on sampleOnly ("Free sample: first 10 numbers, no charge") to validate the first 10 numbers of your list with no charge at all.
Inputs saved for other phone validators also run here: phoneNumbers (or numbers, phone) in place of phones, and defaultCountry / defaultCountryCode in place of defaultRegion. Fields we do not return (includeCarrier, includeGeocoding, includeTimezone, formats, maxConcurrency) are accepted and ignored; maxResults limits the list. Output per row: E.164, validity, line type, country, calling code, national and international format; with includeGeoCarrier, also carrier, region and time zones (offline).
Paste phone numbers in any format, get back E.164, validity, line type and country. 1,000 numbers = $0.50.
| input | e164 | valid | type | country |
|---|---|---|---|---|
| +1 415-555-2671 | +14155552671 | true | FIXED_LINE_OR_MOBILE | US |
| +44 20 7946 0958 | +442079460958 | true | FIXED_LINE | GB |
| (212) 555-0100 | +12125550100 | true | FIXED_LINE_OR_MOBILE | US |
| not a number | null | false | null | null |
Offline format check (libphonenumber): no carrier lookup, no API key. Unparseable rows are free. Rows above are real output of this actor's validator with defaultRegion US.
Pairs with Bulk Email Validator (no SMTP) for lead-list hygiene.
Features
- Per-row status and run summary: every output row has
rowStatus(ok,invalidorerror) androwReason, and each run saves aRUN_SUMMARYrecord in the key-value store with counts per status, rows billed and free rows.
Quick start
Input (phones is the only field you need):
{ "phones": ["+1 415-555-2671", "+44 20 7946 0958", "abc"], "defaultRegion": "US" }
Numbers in a Google Sheet? Set sheetUrl to the share link (shared as "Anyone with the link can view"; converted to CSV export automatically) and optionally sheetColumn: { "sheetUrl": "https://docs.google.com/spreadsheets/d/<id>/edit#gid=0", "sheetColumn": "Phone", "defaultRegion": "US" }.
Output, one row per number (illustrative shape; values for +14155552671):
{ "input": "+1 415-555-2671", "e164": "+14155552671", "valid": true, "possible": true, "type": "FIXED_LINE_OR_MOBILE", "country": "US", "callingCode": "1", "nationalFormat": "(415) 555-2671", "internationalFormat": "+1 415-555-2671", "error": null }
Pricing event: phone-validated, $0.0005 per parseable number; blank or unparseable inputs are free.
Input: phones (list of numbers in any common format), defaultRegion (ISO 2-letter code, used for numbers without a + prefix, default US) and sampleOnly (process only the first 10 numbers, no charge). Inputs saved for other validators also work: phoneNumbers, numbers or phone are accepted in place of phones; phoneNumbersText takes numbers pasted one per line, defaultCountry works like defaultRegion, and onlyValid returns only valid numbers (invalid ones are left out and not charged).
Output per number: input, e164, valid, possible, type (MOBILE, FIXED_LINE, FIXED_LINE_OR_MOBILE, TOLL_FREE, VOIP, ...; null if unknown), country, callingCode, nationalFormat, internationalFormat, error.
Phone number formatter for WhatsApp (E.164 + wa.me link)
Phone number formatter for WhatsApp: E.164 + wa.me click-to-chat link (format only, no WhatsApp account check). The E.164 digits are what a https://wa.me/<digits> link expects. This Actor does not contact WhatsApp and cannot tell you whether a number has a WhatsApp account.
Validate leads from a Google Maps Scraper run
- Run a Google Maps scraper (for example
compass/crawler-google-places) and copy the dataset ID of the run (Storage tab). - Paste it into
inputDatasetId. The actor readsphoneUnformatted,internationalPhoneNumberorphonefrom each place (first one present) and validates it. SetdefaultRegionto the scrape's country for numbers without a+. - Each result row keeps the place's
title,placeId,websiteandaddresswhen present, so you can join results back to the scrape.
Example: { "inputDatasetId": "YOUR_DATASET_ID", "defaultRegion": "US", "onlyValid": true }. This checks format and line type offline; it does not call the number or confirm it is in service.
UK, India and Brazil phone number validator
UK, India and Brazil phone number validator: +44, +91, +55 numbers parsed, validated and formatted offline. Set defaultRegion to GB, IN or BR for local-format numbers, or use the + prefix.
FAQ
How do I convert a list of phone numbers to E.164 in bulk?
Put the numbers in phones and set defaultRegion (for example US, GB, DE) for numbers written without a + prefix. Every row comes back with e164, nationalFormat and internationalFormat. Example input for a mixed list (the first has no +, so defaultRegion is used):
{ "phones": ["(415) 555-2671", "+44 20 7946 0958", "+49 30 123456"], "defaultRegion": "US" }
Numbers that can be parsed cost $0.0005 each ($0.50 per 1,000). Blank or unparseable inputs are returned with an error code and are not charged.
Can I clean a phone list before an SMS campaign?
Partly. Use valid and possible to find numbers that cannot exist (wrong length, no matching numbering-plan range) and type to see line type where the numbering plan says. It does not check whether a number is active, reachable or ported; that needs a paid carrier/HLR lookup. Turn on sampleOnly to run the first 10 numbers of your list free before you pay for the rest.
Is this number mobile or landline?
The type field returns MOBILE, FIXED_LINE, FIXED_LINE_OR_MOBILE, TOLL_FREE, VOIP and other libphonenumber types, or null when unknown. In the US and Canada mobile and landline share ranges, so you will often see FIXED_LINE_OR_MOBILE. This is numbering-plan metadata only, not a carrier check.
Does it work offline, with no API key?
Yes. The Actor runs Google's libphonenumber metadata (via libphonenumber-js) inside the run: no third-party lookup service, no API key and no per-lookup vendor fee. You pay only the Actor's pay-per-event price of $0.50 per 1,000 parseable numbers.
Do I need an API key or external credits?
No. There is no third-party lookup account, API key or prepaid credit balance to top up, so you cannot hit a "no balance" error from an outside service. The only cost is this Actor's pay-per-event charge on your Apify account. Set sampleOnly to validate the first 10 numbers free.
What does it not return?
No live-line / active / reachable / ported status, no WhatsApp or SMS deliverability, no owner name and no personal-data lookup. It returns only what libphonenumber's numbering-plan metadata can say: format, validity, line type and country, plus carrier (original allocation), region and time zones when includeGeoCarrier is on.
I already use libphonenumber. Why pay for this?
You don't have to if you are happy to run it in your own code. Use this Actor when you want phone validation as an API or scheduler step (Make, n8n, Zapier, or a direct API call) or as a one-off CSV job without setting up code. Results match libphonenumber output; there is no extra data beyond that.
What about emails in the same list?
Use Bulk Email Validator (No SMTP) for the email column of the same lead list.
Use it from Google Sheets (=PHONE_E164)
Paste this Apps Script into Extensions > Apps Script, add your own Apify token as script property APIFY_TOKEN (never in the code), then use =PHONE_E164(A2:A50) to get E.164, valid, line type and country per row. It calls this Actor's run-sync-get-dataset-items endpoint on your account.
function PHONE_E164(range, defaultRegion) {var token = PropertiesService.getScriptProperties().getProperty('APIFY_TOKEN');if (!token) throw new Error('Set script property APIFY_TOKEN.');var rows = Array.isArray(range) ? range : [[range]], flat = [];rows.forEach(function (r) { r.forEach(function (c) { flat.push(String(c == null ? '' : c).trim()); }); });var phones = flat.filter(function (p, i) { return p && flat.indexOf(p) === i; });if (!phones.length) return flat.map(function () { return ['', '', '', '']; });var res = UrlFetchApp.fetch('https://api.apify.com/v2/acts/pennydata~phone-number-validator-offline/run-sync-get-dataset-items?format=json&clean=true', {method: 'post', contentType: 'application/json', headers: { Authorization: 'Bearer ' + token },payload: JSON.stringify({ phones: phones, defaultRegion: defaultRegion || 'US' }), muteHttpExceptions: true });if (res.getResponseCode() >= 300) throw new Error('Apify HTTP ' + res.getResponseCode());var by = {}; JSON.parse(res.getContentText()).forEach(function (it) { by[it.input] = it; });return flat.map(function (p) { var it = by[p]; return !p ? ['', '', '', ''] : !it ? ['no result', '', '', ''] : [it.e164 || '', it.valid === true, it.type || '', it.country || '']; });}
Runs are billed to your Apify account at the per-number price below.
Pricing
Pay per event, no start fee. Prices match .actor/pay_per_event.json.
| Event | Price | When it is charged |
|---|---|---|
phone-validated | $0.0005 per number ($0.50 per 1,000) | One number that could be parsed and returned (valid or invalid) |
| Blank or unparseable input | Free | Returned with an error code, never charged |
Example: 1,000 inputs of which 40 are blank or unparseable cost 960 x $0.0005 = $0.48. Set a maximum cost per run in the run options; the actor stops charging when that limit is reached. Apify platform usage is billed separately if your plan includes it.
Honest limits
- Offline only. No carrier lookup, no HLR, no "is this number active/reachable/ported" check, no owner or personal-data lookup.
validmeans the number matches a real numbering plan range; it may not be assigned to anyone. - Line type comes from libphonenumber metadata and is not always determinable (US numbers are often
FIXED_LINE_OR_MOBILE). - Time zones come from libphonenumber metadata (opt-in via
includeGeoCarrier); where an area spans several zones all are returned. - Numbers without a
+prefix usedefaultRegion; a wrong region gives wrong results. - Metadata is as current as the bundled library version.
Not affiliated with Google or the libphonenumber project. Written with the assistance of an AI (Claude Sonnet 5.5).
Switching from another phone validator
Paste the input you already use and change only the actor ID. These keys are accepted as aliases:
| Other validator's input | Used here as |
|---|---|
phoneNumbers, numbers, phone, phoneNumbersText (list, text or {phone} objects) | phones |
defaultCountry, defaultCountryCode, country | defaultRegion |
maxResults | cap on numbers processed |
includeCarrier, includeGeocoding, includeTimezone, formats, maxConcurrency | accepted and ignored (use includeGeoCarrier for offline carrier, region and time zone) |
Input is compatible; the output field names are this actor's own (e164, valid, type, country), so check your downstream mapping once.
Related actors
Other small pay-per-event Actors from the same publisher:
- Bulk Email Validator (No SMTP): validate the email column of the same lead list.
- Website Contact Extractor: pulls phone numbers from websites so you can validate them here.
- Shopify Store Leads & Contacts: store contact data to run through the validator.
Geo and carrier (optional)
Set includeGeoCarrier to add carrier, geoLocation (city/region, e.g. US area-code city and state) and timeZones (IANA names) to valid numbers. Offline lookup from libphonenumber metadata: carrier is the original allocation and ignores number porting; many fixed-line numbers have no carrier. Off by default.