# Phone Number Validation & Lookup: Format, Carrier, Line Type (`data-done-right/phone-number-validation`) Actor

Phone number validation API and phone number validator: validate phone numbers in bulk. Phone number lookup and carrier lookup with country, city, time zones and line type (mobile, landline, VoIP, toll free), plus E.164, international, national and RFC3966 formats. Offline, no API key.

- **URL**: https://apify.com/data-done-right/phone-number-validation.md
- **Developed by:** [Data Done Right](https://apify.com/data-done-right) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.68 / 1,000 numbers

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Phone Number Validation & Lookup: Format, Carrier, Line Type

This **phone number validation** Actor checks a list of phone numbers and tells you, for each one, whether it is valid, how to write it (E.164, international, national, RFC 3966), which country it belongs to, what kind of line it is (mobile, fixed line, VoIP, toll free, premium rate...), which carrier originally got the number range, and where the area code is (city or region and time zones). Use it as a **phone number validator** and **phone number lookup** for lead lists, CRM cleanup, sign-up forms, SMS campaigns and data pipelines. It runs **offline**: no API key, no third-party service, no calls to the numbers. It uses the `phonenumbers` library, a Python port of Google's libphonenumber, so large lists run in minutes.

### What can you do with a phone number validator

- **Validate phone numbers in bulk.** Paste numbers in any common format (`+1 (201) 555-0123`, `415.555.2671`, `0044 20 7946 0958`, `tel:+49-30-901820`). Each number becomes one row.
- **Normalize to E.164 and other formats.** Get E.164, international, national and RFC 3966 (`tel:`) versions of every number, ready for a CRM, an SMS provider or a database key.
- **Carrier lookup.** The `carrier` column shows the carrier that originally received the number range (mobile numbers, in countries where this data exists).
- **Country, city and time zones.** ISO country code, country name, city or region of the area code, and the IANA time zones of the number's area.
- **Line type.** `mobile`, `fixed_line`, `fixed_line_or_mobile`, `toll_free`, `premium_rate`, `shared_cost`, `voip`, `personal_number`, `pager`, `uan`, `voicemail` or `unknown`.
- **Possible vs valid.** `isPossible` is a quick length check (a local number without an area code does not count), `isValid` checks the full numbering plan of the country. A `reason` column says why a number failed.
- **Clean lists.** Turn on **De-duplicate** to check each distinct number once (two writings of one number count as one), or **Only return valid numbers** to get a clean list back.

### Phone number lookup and carrier lookup: what the results mean

Please read this before you rely on the results.

- **Valid means the number fits the numbering plan**: the country code exists, the length is right and the digits match a pattern the country assigns. It does **not** mean the line is active, connected, reachable or owned by a real person. A number that passes can still be disconnected, and a freshly assigned number can still be flagged as invalid until the library's data is updated.
- **Carrier is the original carrier of the number range.** It comes from the prefix, so it does **not** reflect number portability: a number moved to another carrier still shows the first one. Carrier data exists mostly for mobile numbers and only in some countries; many rows have none.
- **Line type is also a numbering-plan answer.** In several countries (the US and Canada, for example) mobile and landline numbers share the same ranges, so you get `fixed_line_or_mobile`. VoIP is only detected where the numbering plan sets VoIP ranges aside; a VoIP service that rents ordinary mobile or landline numbers looks like an ordinary number.
- **Location is the area code's region**, not where the person is. Mobile and toll-free numbers usually have no location, and `location` is empty when only the country is known.
- For an invalid number, `regionCode` and `country` are filled only when the country code belongs to a single country. Toll-free numbers can list many time zones.
- No SMS, voice call or network lookup is made. If you need to know whether a line is live, you need a live HLR or SMS verification service. This Actor is the fast, cheap first filter in front of one.

### How to validate phone numbers

1. Paste your numbers into **Phone numbers**, one per line.
2. Pick **Default country** for numbers written without a `+` country code (national format). Numbers that start with `+` ignore it. A leading `00` is read as `+` when that makes the number valid.
3. Choose the **output formats** and which extra columns you want (line type, carrier, location, time zones).
4. Run it and download the rows as JSON, CSV or Excel, or read them through the Apify API.

### Input example

```json
{
  "phoneNumbers": [
    "+1 (201) 555-0123",
    "415.555.2671",
    "0044 20 7946 0958",
    "+44 7400 123456",
    "+1-800-555-0199",
    "12345"
  ],
  "defaultCountry": "US",
  "outputFormats": ["e164", "international", "national", "rfc3966"],
  "includeNumberType": true,
  "includeCarrier": true,
  "includeLocation": true,
  "includeTimeZones": true,
  "onlyValid": false,
  "dedupe": true,
  "maxNumbers": 100000
}
```

All of these except `phoneNumbers` are optional. The numbers above are libphonenumber's own example numbers and fictional 555 numbers.

### Output

One row per number:

```json
{
  "index": 3,
  "original": "+44 7400 123456",
  "e164": "+447400123456",
  "international": "+44 7400 123456",
  "national": "07400 123456",
  "rfc3966": "tel:+44-7400-123456",
  "countryCode": 44,
  "regionCode": "GB",
  "country": "United Kingdom",
  "isPossible": true,
  "isValid": true,
  "numberType": "mobile",
  "carrier": "Three",
  "location": null,
  "timeZones": ["Europe/Guernsey", "Europe/Isle_of_Man", "Europe/Jersey", "Europe/London"],
  "extension": null,
  "reason": null
}
```

- `index` is the position of the number in your input list (0-based, blank lines ignored), so you can join the results back to your data.
- An invalid number gets `isValid: false` and a `reason` such as "Too short for this country", "Too long to be a phone number", "Not a phone number" or "No usable country code: write the number with +<country code> or set Default country".
- Formats (`e164`, `international`, `national`, `rfc3966`) are filled whenever the length is possible, even if the number is not valid. They are `null` for text that cannot be read as a number.
- Switching an option off removes that column from the rows.
- Extensions in the input (`x123`, `ext. 5`) are kept in `extension` and in the national, international and RFC 3966 formats, not in E.164.
- A **SUMMARY** record in the key-value store counts valid and invalid numbers, numbers by type and country, duplicates skipped, and the version of the phone metadata used. A **NOTES** record lists anything skipped.

### Phone number validation API

Call this Actor from the Apify API, Python, JavaScript, Make, Zapier or n8n as a **phone number validation API** with no key of your own to manage. Example with the Apify Python client:

```python
from apify_client import ApifyClient

run = ApifyClient("<APIFY_TOKEN>").actor("data-done-right/phone-number-validation").call(run_input={
    "phoneNumbers": ["+1 (201) 555-0123", "415.555.2671", "+44 20 7946 0958"],
    "defaultCountry": "US", "outputFormats": ["e164"], "onlyValid": True})
for row in ApifyClient("<APIFY_TOKEN>").dataset(run["defaultDatasetId"]).iterate_items():
    print(row["original"], "->", row["e164"], row["numberType"], row["carrier"])
```

Runs take seconds because nothing leaves the Actor: the numbers are checked against the libphonenumber data built into it.

### Use it in Claude, ChatGPT and Cursor

Connect Apify's MCP server (mcp.apify.com) and your AI assistant can validate phone numbers itself. For example: "validate these 200 numbers from my CRM export, assume they are UK numbers, and list the mobile ones in E.164." The only required input is `phoneNumbers`; set `defaultCountry` for numbers without a `+`.

### Use cases

- **CRM and lead-list cleanup:** one E.164 format for every contact, invalid and duplicate numbers flagged before you import.
- **SMS and WhatsApp campaigns:** keep mobile numbers and drop landlines and toll-free numbers before you send.
- **Sign-up and checkout forms:** validate on the server with a single API call.
- **Call routing and time-zone-aware dialing:** use country, location and time zones to decide when and where to call.
- **Data pipelines and enrichment:** add country, line type and carrier columns to a contact table.

### How much does it cost

Pay per event: **$0.00085 per phone number** (`number`), charged once for every number checked, valid or not, because "this number is invalid" is the answer you asked for. 1,000 numbers cost about $0.85, and 100,000 about $85. Paid Apify plans get 10% (Silver) to 20% (Gold and up) off. Duplicates skipped by **De-duplicate**, blank lines and numbers beyond **Max numbers** are not charged. **Only return valid numbers** hides invalid rows from the results but they are still checked and charged. If you set a maximum spend per run, the Actor stops cleanly when it is reached and keeps the rows already delivered. A run with no phone numbers fails with a clear message and charges nothing.

### FAQ

#### How do I validate phone numbers in bulk?

Paste them into **Phone numbers**, set **Default country**, and run. You get one row per number with `isValid`, the formats and the details. Lists of 100,000 numbers or more are fine; raise **Max numbers** if you need more than the default cap.

#### Does it call or text the numbers?

No. Nothing is dialed and no message is sent. The Actor never contacts the people behind the numbers, and it makes no network request to look anything up. The result comes from the numbering-plan data in the library.

#### Does a valid number mean the phone is active?

No. Valid means the number is correctly formed for its country. It can still be unassigned, disconnected or unreachable. Use a live HLR or SMS check if you need to know that.

#### Is the carrier the current carrier of the number?

No. It is the carrier the number range was originally assigned to. Because of number portability, the number may now be with a different carrier.

#### Why is the line type `fixed_line_or_mobile` for US numbers?

In the US and Canada, mobile and landline numbers come from the same ranges, so the numbering plan cannot tell them apart. The Actor reports that honestly instead of guessing.

#### What if my numbers have no country code?

Set **Default country**. Numbers without a `+` are read as national numbers of that country. Numbers that start with `+` always keep their own country code. If you leave the default empty, national numbers come back invalid with a reason that says so.

#### Does it remove duplicates?

Yes, by default. Different writings of the same number (`+1 201 555 0123`, `(201) 555-0123`, `201.555.0123`) count as one, and the same number with a different extension counts as a different number. Turn off **De-duplicate** to get one row per input line.

#### Which countries does it support?

All 245 regions that libphonenumber covers, plus non-geographic numbers such as +800. Carrier and city data is richer for some countries than others.

#### Is it OK to process phone numbers under GDPR?

Phone numbers are personal data when they can identify a person. The Actor processes the numbers you give it only to validate them, writes the results to your run's storage in your Apify account, and makes no outside calls. You remain responsible for having a lawful basis to process the numbers, for what you do with the results, and for deleting the run's data when you no longer need it. Never use the output to contact people who have not agreed to be contacted.

#### How current is the data?

The numbering-plan data is that of the pinned `phonenumbers` version, shown in the `libphonenumberVersion` field of the SUMMARY record. New number ranges are added when the library is updated, so a very recently assigned range can show as invalid until then.

### Related tools

- **Google Sheets Import & Export: Apify Data, No Login** sends the validated results to a Google Sheet.
- **HTTP Request Runner: Bulk API Calls, Retries, Proxies** calls your own API for each valid number.
- **Company Enrichment API: Domain to Tech, Jobs & Socials** enriches the companies behind your cleaned leads from their domains.

# Actor input Schema

## `phoneNumbers` (type: `array`):

The phone numbers to validate, one per line, in any common format. Numbers with a + country code work as they are; numbers without one use Default country. Example: +1 (201) 555-0123, 415.555.2671, 0044 20 7946 0958, +49 30 901820. Duplicates are skipped when De-duplicate is on.

## `defaultCountry` (type: `string`):

Country used to read numbers written without a + country code, such as (415) 555-2671. Numbers that start with + ignore it. Pick the country most of your list comes from.

## `outputFormats` (type: `array`):

Which formatted versions of each valid or possible number to return: E.164 (+12015550123), international (+1 201-555-0123), national ((201) 555-0123) and RFC 3966 (tel:+1-201-555-0123).

## `includeNumberType` (type: `boolean`):

Add numberType: mobile, fixed_line, fixed_line_or_mobile, toll_free, premium_rate, shared_cost, voip, personal_number, pager, uan, voicemail or unknown.

## `includeCarrier` (type: `boolean`):

Add the carrier that originally got the number range (mobile numbers in countries where data exists). Ported numbers are not reflected.

## `includeLocation` (type: `boolean`):

Add location: the city or region of the number's area code, where the numbering plan allows it. Mobile and toll-free numbers usually have none.

## `includeTimeZones` (type: `boolean`):

Add timeZones: the IANA time zones the number's area belongs to, for example America/New_York.

## `onlyValid` (type: `boolean`):

Leave invalid numbers out of the results. They are still checked and charged, because telling you a number is invalid is the answer. The SUMMARY record still counts them.

## `dedupe` (type: `boolean`):

Check each distinct number once. Two writings of the same number (+1 201 555 0123 and (201) 555-0123) count as one. Duplicates are not charged and not returned; the SUMMARY counts them.

## `maxNumbers` (type: `integer`):

Hard cap on how many numbers are processed (and charged) in this run. Extra numbers are skipped and noted in the NOTES record.

## Actor input object example

```json
{
  "phoneNumbers": [
    "+1 (201) 555-0123",
    "415.555.2671",
    "+44 20 7946 0958",
    "+44 7400 123456",
    "+1-800-555-0199",
    "12345"
  ],
  "defaultCountry": "US",
  "outputFormats": [
    "e164",
    "international",
    "national",
    "rfc3966"
  ],
  "includeNumberType": true,
  "includeCarrier": true,
  "includeLocation": true,
  "includeTimeZones": true,
  "onlyValid": false,
  "dedupe": true,
  "maxNumbers": 100000
}
```

# Actor output Schema

## `results` (type: `string`):

One item per phone number: formats, country, validity, line type, carrier, location and time zones (all result items of this run, as JSON, CSV, Excel and more).

## `records` (type: `string`):

Key-value store records: the run summary (valid and invalid counts, numbers by type and country) and notes on skipped numbers.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "phoneNumbers": [
        "+1 (201) 555-0123",
        "415.555.2671",
        "+44 20 7946 0958",
        "+44 7400 123456",
        "+1-800-555-0199",
        "12345"
    ],
    "defaultCountry": "US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("data-done-right/phone-number-validation").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "phoneNumbers": [
        "+1 (201) 555-0123",
        "415.555.2671",
        "+44 20 7946 0958",
        "+44 7400 123456",
        "+1-800-555-0199",
        "12345",
    ],
    "defaultCountry": "US",
}

# Run the Actor and wait for it to finish
run = client.actor("data-done-right/phone-number-validation").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "phoneNumbers": [
    "+1 (201) 555-0123",
    "415.555.2671",
    "+44 20 7946 0958",
    "+44 7400 123456",
    "+1-800-555-0199",
    "12345"
  ],
  "defaultCountry": "US"
}' |
apify call data-done-right/phone-number-validation --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,data-done-right/phone-number-validation"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Vyu3RM1iYNU1nAl4H/builds/DaheiRMz5dlxF4fp4/openapi.json
