Phone Number Validator & Formatter – E.164, Bulk, Offline avatar

Phone Number Validator & Formatter – E.164, Bulk, Offline

Pricing

from $0.80 / 1,000 phone numbers

Go to Apify Store
Phone Number Validator & Formatter – E.164, Bulk, Offline

Phone Number Validator & Formatter – E.164, Bulk, Offline

Bulk phone validator and phone number formatter: validate, format to E.164 and deduplicate phone numbers offline with Google's libphonenumber. Country, line type and time zone per number. Checks plausibility, not whether a line is active. $0.0008 per phone number + $0.00005 per run.

Pricing

from $0.80 / 1,000 phone numbers

Rating

0.0

(0)

Developer

Jacob Calmelat

Jacob Calmelat

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Phone number validator & formatter: what a full run gives you

Paste a list of phone numbers (or send a CSV column through the API) and get back, for every number, one row like this (real output from the Actor's code for (650) 253-0000 with default country US, shortened):

{"input": "(650) 253-0000", "isValid": true, "e164": "+16502530000", "international": "+1 650-253-0000",
"national": "(650) 253-0000", "regionCode": "US", "numberType": "FIXED_LINE_OR_MOBILE",
"timeZones": ["America/Los_Angeles"], "billable": true, "error": null}
  • Phone validator: valid / invalid against the country's numbering plan (plausibility, not whether the line is active).
  • Phone number formatter: E.164, international and national format, ready for HubSpot, Salesforce, Twilio.
  • Deduplication: spelling variants of one number count once. Unparseable inputs come back with an error code and are not charged.
  • Price: $0.0008 per analysed phone number + $0.00005 per run. Set "Max cost per run" to cap spend.
  • Free Apify plan: the first 100 numbers of each run are processed so you can check the output on your own data; the rest are skipped and not charged. A paid Apify plan processes the whole list (up to 100,000 numbers per run) at the same price per number.

What does this phone number validator & E.164 formatter do?

Clean and standardise phone-number lists in bulk. This phone number validator and formatter gives you, for every number:

  • valid / invalid against the official numbering plan
  • E.164, international and national formats
  • country, line type (mobile, fixed line, toll-free, VoIP…)
  • original carrier (where known), location and time zones

The Actor runs entirely offline using Google's open-source libphonenumber metadata. It calls no third-party API and visits no website.

What "valid" means: this Actor checks that a number is correctly formatted and plausible under the numbering plan of its country. It does not check whether a line is active, in service, owned by a particular person, or reachable. It makes no network or carrier (HLR) lookups.

Typical uses of a bulk phone number validator

  • Normalise CRM, lead or customer lists to E.164 before importing them into HubSpot, Salesforce, Twilio and similar tools.
  • Remove malformed and impossible numbers before an SMS or calling campaign (you're responsible for consent and compliance).
  • Segment by country, line type or time zone, for example to call mobiles only during local business hours.
  • Deduplicate numbers written in different formats: (650) 253-0000, +1 650 253 0000 and 6502530000 count as one.

How to validate and format phone numbers in bulk

  1. Paste numbers into Phone numbers, one per line, or send them as a JSON array through the API.
  2. Set Default country for numbers written without a + prefix (for example US, GB, DE).
  3. Optionally set Max numbers to process and a Max cost per run to cap your spend.
  4. Run the Actor, then download the results as CSV, Excel or JSON, or fetch them through the API.

Example input

{
"phoneNumbers": ["+1 650-253-0000", "020 7031 3000", "0412 345 678", "not a number"],
"defaultCountry": "GB",
"maxItems": 1000,
"deduplicate": true,
"includeCarrierAndLocation": true
}

Example output (one item per number)

{"input":"+1 650-253-0000","billable":true,"isValid":true,"isPossible":true,
"e164":"+16502530000","international":"+1 650-253-0000","national":"(650) 253-0000",
"countryCallingCode":1,"regionCode":"US","numberType":"FIXED_LINE_OR_MOBILE",
"carrier":null,"location":"Mountain View, CA","timeZones":["America/Los_Angeles"],"error":null}

Values that can appear in error:

  • Analysed but failed: INVALID_NUMBER. The number parsed but doesn't match its country's numbering plan.
  • Rejected: NOT_A_NUMBER, INVALID_COUNTRY_CODE, TOO_SHORT_NSN, TOO_SHORT_AFTER_IDD, TOO_LONG, EMPTY, INPUT_TOO_LONG, NOT_A_STRING.
  • Status row (free): MAX_COST_TOO_LOW or TIMEOUT_GUARD appears as a single non-billable row when a run could deliver nothing, for example when "Max cost per run" is below the price of one number.

A bad row never stops the run. A SUMMARY record in the run's key-value store shows the totals: processed, billable, non-billable, duplicates skipped, truncated, and the stop reason.

Pricing (pay per event)

  • $0.0008 per billable number ($0.80 per 1,000) plus $0.00005 per run (Apify's standard "Actor Start" event, $0.05 per 1,000 runs). Platform usage (compute, storage) is included: you pay only these two events.
  • Billable: any number that was successfully parsed and analysed, whether it turns out valid or invalid. You get a real numbering-plan verdict for it.
  • Never billable:
    • rejected or unparseable inputs (error is one of the "Rejected" codes above; billable: false)
    • duplicates that were skipped
    • numbers cut off by maxItems, the free-plan limit or your max-cost limit
    • anything not delivered to your dataset
  • Spending limit: the Actor respects your Max cost per run. The $0.01 minimum covers the start fee plus 12 numbers ((0.01 − 0.00005) / 0.0008 = 12.4, rounded down). The run then stops cleanly, and everything already delivered is kept.
  • Free Apify plan: up to 100 numbers per run.

Examples: 1,000 numbers = $0.80005; 10,000 numbers = $8.00005; a 10-number run = $0.00805.

How it compares

Checked on the Apify Store on 2026-10-23 (prices change; verify before you decide):

This ActorLive lookup / messaging-app validators
Price per number$0.0008 (+ $0.00005 per run)about $0.001 to $0.06, depending on the data returned
Checks format and plausibility (E.164, country, line type)yesusually yes
Tells whether a line is active, or registered on WhatsApp/Telegramnoyes
Names the owner of a number (reverse lookup)nosome do
Numbers leave the Actor runno: fully offlineusually yes: they query external services

Good combination: clean and deduplicate your list here first ($0.80 per 1,000), then send only the plausible numbers to a paid live-lookup service, so you do not pay for impossible numbers. Choose something else if you need to know whether a line is live or who owns it.

Use it in your workflow

  • Spreadsheets and automations: copy a phone column into the input, or connect the Actor through Apify's integrations (for example Make, Zapier, n8n or Google Sheets).
  • Schedule it to clean new leads on a timetable, and filter on isValid, numberType or billable.
  • AI agents: MCP-compatible assistants can call the Actor through the Apify MCP server. The input is a plain list of numbers and the output is flat JSON.

Recipes: Python, curl, n8n, Make, Zapier, Google Sheets

curl (synchronous, waits up to 300 s; good for lists up to a few thousand numbers):

curl -X POST "https://api.apify.com/v2/actors/shephouse~phone-number-validator-offline/run-sync-get-dataset-items?maxTotalChargeUsd=1" \
-H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
-d '{"phoneNumbers":["(650) 253-0000","020 7946 0018"],"defaultCountry":"US"}'

maxTotalChargeUsd is a hard cap on what the call can charge. Keep your token in an environment variable, never in a shared file.

n8n, Make, Zapier: use an HTTP request step with the URL, header and JSON body above, then filter the returned array on isValid (n8n: HTTP Request node + Code node; Make: HTTP > Make a request + Iterator + Filter; Zapier: Webhooks by Zapier > Custom Request). Apify also offers official n8n, Make and Zapier integrations that run an Actor and read its dataset.

Pick the right default country. Numbers without a + are interpreted with defaultCountry, so the same text can be valid or invalid:

inputdefaultCountryresult
020 7946 0018GBvalid, +442079460018
020 7946 0018USinvalid
(650) 253-0000USvalid, +16502530000
(650) 253-0000GBinvalid

If your list mixes countries, run one batch per country or ask the source for numbers with a + prefix. A second spelling of a number you already submitted (for example +1 650 253 0000 after (650) 253-0000) is skipped as a duplicate and not charged, so map results back by e164, not by row position.

Privacy, retention and data processing

  • Numbers are processed only inside your own Actor run on the Apify platform. They are never sent to any third-party service, and the developer does not copy them elsewhere.
  • Results are stored in your run's default dataset and key-value store and follow your Apify account's data-retention settings. You can delete them at any time.
  • The run log shows only counts, never the numbers themselves.
  • Phone numbers can be personal data. You are responsible for having a lawful basis to process them (for example under GDPR or CCPA).
  • Metadata comes from libphonenumber (Apache-2.0) via the phonenumbers Python package.

Limitations

  • The Actor can't confirm that a line is live, ported, disconnected or reachable.
  • Carrier is the operator the number range was originally allocated to. It doesn't reflect porting, and it is often empty (including for most US numbers).
  • Location is approximate (region or city level).
  • Accuracy depends on the bundled libphonenumber metadata release, which is updated periodically.
  • Up to 100,000 numbers per run, and each input must be 64 characters or fewer.

FAQ

How do I convert phone numbers to E.164 format?

Paste your numbers, set the Default country for numbers written without a +, and run. Every parsed number comes back as e164, for example +16502530000. E.164 is the ITU-T international numbering format (+, country code, subscriber number, max. 15 digits) expected by Twilio, HubSpot, Salesforce and most SMS/CRM APIs.

Does it check whether a phone number is active or reachable?

No. It validates format and plausibility against the numbering plan of the country (the same rules as Google's libphonenumber). It does not call carriers, send SMS or do HLR lookups, so it cannot tell whether a line is live, ported or owned by a person.

Can I use it from Python, JavaScript or the Apify API?

Yes. Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("shephouse/phone-number-validator-offline").call(
run_input={"phoneNumbers": ["+1 650-253-0000", "020 7031 3000"], "defaultCountry": "GB"})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["e164"], item["isValid"], item["numberType"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('shephouse/phone-number-validator-offline').call({ phoneNumbers: ['+1 650-253-0000'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Why is a number that looks right marked invalid?

The check follows the numbering plan of the number's country: a wrong length, an unassigned prefix or a missing country code makes a number invalid or only "possible". For local numbers without a +, set Default country correctly (for example GB for UK numbers).

Is it worth paying for this if live lookups exist?

Live lookups answer a different question (is the line active, or who owns it) and usually cost more per number. This Actor is for the cheap first pass: normalise to E.164, drop impossible numbers and duplicates, and see country and line type, before you spend on anything else.

Can I validate a column from a spreadsheet or CSV?

Yes. Paste the column into Phone numbers (one per line), or send the values as a JSON array through the API, and download the results as CSV, Excel or JSON.

How many numbers can I validate per run and what does it cost?

Up to 100,000 numbers per run at $0.80 per 1,000 (see Pricing below). Use Max cost per run to cap spend.

Does it work for every country?

It supports all regions covered by libphonenumber (over 200). Line-type and carrier detail varies by country; see Limitations.

Is my data sent to third parties?

No. The Actor runs offline and calls no external service (see Privacy).

Changelog

  • 0.4.6: listing and documentation: clearer title and description, a "what a full run gives you" section, clearer input help and free-plan message. No change to validation, billing or pricing.
  • 0.4.4: documentation only: recipes (curl, n8n, Make, Zapier), default-country table, duplicate-handling note. No change to behavior or pricing.
  • 0.4.3: documentation only: comparison table, workflow and AI-agent section, more FAQ answers. No change to behavior or pricing.
  • 0.4.1: listing and documentation update only (README structure, FAQ, API examples, SEO fields). No change to behaviour or pricing.
  • 0.4: a run that can deliver nothing (cost limit below one number, or timeout) now returns one free status row instead of an empty dataset; verified locally with the default (prefill) input: Succeeded and non-empty dataset.
  • 0.3: pricing documentation updated for the per-run start event ($0.00005); stricter guard against unexpected priced events.
  • 0.2: pay-per-event billing only for analysed numbers; deduplication by E.164; free-plan limit; spending-limit handling; billable field; safeguard against pricing misconfiguration.
  • 0.1: first private version.

Support

Open an Issue on this Actor's page with your run ID, but do not paste real phone numbers. We aim to reply within 2 business days.