Phone Number Validator
Pricing
from $1.00 / 1,000 number validateds
Phone Number Validator
Validate phone numbers offline with Google's libphonenumber. Get validity, number type (mobile, landline, VOIP, toll-free), country, and E.164/international/national formats. Never charged for an invalid number.
Pricing
from $1.00 / 1,000 number validateds
Rating
0.0
(0)
Developer
Adrian Voss
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
20 hours ago
Last modified
Categories
Share
You paste a list of phone numbers and get back, per number, whether it's a real, validly formatted number — plus its type (mobile, landline, VOIP, toll-free...), country, and E.164/international/national formats. Every answer comes from Google's libphonenumber, computed entirely offline: no third-party API, no scraping, no network request of any kind. That also means no rate limit, no blocking, and no per-call vendor cost — you're only ever charged for a number libphonenumber actually confirms is real.
Who it's for
Anyone who needs to clean a list of phone numbers before it hits a dialer, a CRM, an SMS campaign, or a lead-gen pipeline: sales-ops teams deduping a contact export, form-validation services checking a signup field server-side, or an AI agent that just scraped a list of numbers off the web and needs to know which ones are even worth trying. If your list mixes real numbers with typos, placeholders, and copy-paste garbage, this sorts them before you spend money dialing or texting a dead number.
Why offline
Most "phone validator" actors on Apify wrap a paid third-party API (Twitter's account-lookup tricks, a paid HLR/carrier-lookup service, or phoneinfoga-style OSINT scraping) — that means per-lookup vendor cost, rate limits, and a network round trip per number. This actor's validation logic is the same open-source number-plan metadata Android and Google's own products ship with: no vendor in the loop, no network call, no rate limit, and results in milliseconds. The trade-off is honesty about scope — see What you don't get below.
What you get
- isValid — confirmed against libphonenumber's real per-country number-plan rules (not just "the right number of digits").
- isPossible — true whenever the length is plausible for the country, even if
isValidturns out false. Exposed separately so you can see why a number failed, not just that it did. - numberType — MOBILE, FIXED_LINE, FIXED_LINE_OR_MOBILE, VOIP, TOLL_FREE, PREMIUM_RATE, PERSONAL_NUMBER, PAGER, UAN, VOICEMAIL, or UNKNOWN, per libphonenumber's own classification.
- regionCode, countryCallingCode — the ISO country and dialing code the number resolves to.
- e164Format, internationalFormat, nationalFormat — libphonenumber's three standard renderings, ready to paste into a dialer or an SMS API.
What you don't get
Carrier name. Google's real carrier-name mapping (e.g. "this is a Verizon number") is a separate, proprietary dataset that was never released for the open-source JS library this actor uses — anyone claiming to give you a live carrier name from a client-side/offline library is either calling a paid HLR lookup behind the scenes or guessing from the prefix (which goes stale the moment a number is ported). This actor doesn't fabricate that field.
How to use
- In the Apify Console. Open the actor page and click Start — the
phoneNumbersfield is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found. - Via the API. Call it directly with a POST request — no Console needed once you have an API token:
curl "https://api.apify.com/v2/acts/accountable_eel~phone-number-validator/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"phoneNumbers":["+14155552671","+442071838750"]}'
- On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.
Input
{"phoneNumbers": ["+14155552671","+442071838750"]}
One phone number per line. International format with a leading + is always safe (e.g. +14155552671); a number in national format (e.g. 4155552671) needs the optional "Default country" field set below. Accepted formats: +14155552671, +44 20 7183 8750, (415) 555-2671 with Default country = US.
phoneNumbers is a list of phone numbers in any format — E.164 (with a leading +) is always
safe with no other input needed. A number in national format (no +, e.g. 4155552671 or
(415) 555-2671) needs the optional Default country field set to a 2-letter ISO code
(e.g. "US"), since libphonenumber needs a region hint to interpret a number with no country
code embedded in it. One dataset row is returned per item; rows with "found": false are
never charged.
Output
One row per item, for example:
| query | found | status | isValid | isPossible | regionCode | numberType | countryCallingCode | e164Format | internationalFormat | nationalFormat | scrapedAt |
|---|---|---|---|---|---|---|---|---|---|---|---|
| +14155552671 | true | OK | true | true | US | FIXED_LINE_OR_MOBILE | 1 | +14155552671 | +1 415-555-2671 | (415) 555-2671 | 2026-08-31T06:01:41.060Z |
A miss comes back as a row with "found": false and is never charged.
Pricing
$2 per 1,000 phone numbers, plus a $0.00005 start fee. Misses (found:false) are never charged.
Use it from Clay, n8n, Make, or an AI agent
This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.
curl "https://api.apify.com/v2/acts/accountable_eel~phone-number-validator/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"phoneNumbers":["+14155552671","+442071838750"]}'
n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~phone-number-validator/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"phoneNumbers":["+14155552671","+442071838750"]} (swap in an expression from an earlier node for a real value).
Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~phone-number-validator/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"phoneNumbers":["{{phone number}}"]}, mapping the row's phone number into the phoneNumbers array.
MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Phone Number Validator | Apify" — the agent will find and run this actor.
Tips
- Always prefer E.164 input (
+14155552671) when you have it — it's unambiguous and needs no Default country field, and it's what most CRMs and dialers store anyway. - Set Default country once per run if your whole list is from a single country in national format (e.g. a US-only contact export) — it applies to every row in that run.
- A row with
isPossible: truebut no row at all (billed asfound: false) means the number has a plausible length for its country but doesn't match any real, allocated number pattern — treat it as suspicious even though the digit count "looks right".
FAQ
Does this actually call the phone number or a carrier network? No. Nothing is dialed, no SMS is sent, and no network request of any kind is made — this is pure offline computation against libphonenumber's bundled number-plan metadata, the same library Android's own dialer uses to validate numbers as you type.
Why is a number marked invalid when it "looks right" (correct digit count)?
Digit count alone isn't enough — isPossible covers that. isValid additionally checks the
number against the real allocated prefix ranges for its country, so an unallocated or
fictional-format number (right length, wrong pattern) correctly comes back invalid — and
isn't charged.
Can I get the carrier name (e.g. "Verizon", "T-Mobile")? No — see What you don't get above. That data isn't in the open-source library this actor uses, and this actor won't guess it from the prefix.