# Phone Number Validator (`deriverge/phone-number-validator`) Actor

Checks phone numbers from a list or a dataset offline and returns E.164, international and national formats, country, line type, original carrier and time zones. Every invalid number gets a reason, such as too short or no country code.

- **URL**: https://apify.com/deriverge/phone-number-validator.md
- **Developed by:** [deriverge s.r.o.](https://apify.com/deriverge) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.28 / 1,000 phone 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 Validator

Phone Number Validator checks a list of phone numbers and returns one row per number: whether it is valid, its E.164, international and national formats, the country, the line type (mobile, fixed line, toll free and others), the carrier the number range was assigned to, its time zones and, for an invalid number, the reason. Paste numbers into **Phone numbers**, set **Default country** and click **Start**. The check runs offline against Google's libphonenumber data, so it cannot tell whether a valid number is switched on or in use. It costs $0.55 per 1,000 phone numbers on the Free plan ($0.275 on Business), and the $5 of monthly credit in Apify's Free plan covers about 9,000 phone numbers.

### What data does it return?

| Field | Description |
|---|---|
| `input`, `position` | The number as you gave it and its place in the input, starting at 1. |
| `valid` | `true` when the number belongs to a range assigned in its country, such as a real UK mobile range. |
| `possible` | `true` when the number of digits fits the country, even if the range is not assigned. |
| `e164` | The number in E.164 form for databases and SMS gateways, such as `+447400123456`. `null` when the length does not fit any country. |
| `international`, `national` | The number formatted for calling from abroad (`+44 7400 123456`) and inside the country (`07400 123456`). |
| `rfc3966` | A `tel:` link, such as `tel:+44-7400-123456`, with `;ext=` when there is an extension. |
| `countryCode`, `countryName`, `countryCallingCode` | ISO two-letter code (`GB`), English name (`United Kingdom`) and calling code without + (`44`). |
| `nationalNumber`, `extension` | Digits after the calling code, and the extension written after the number (`ext. 12`, `x 12`). |
| `lineType` | `MOBILE`, `FIXED_LINE`, `FIXED_LINE_OR_MOBILE`, `TOLL_FREE`, `PREMIUM_RATE`, `SHARED_COST`, `VOIP`, `PERSONAL_NUMBER`, `PAGER`, `UAN` or `VOICEMAIL`; `null` for an invalid number. |
| `carrier` | Mobile network the number range was originally assigned to, such as `Vodafone` or `O2`. Only for mobile and pager numbers. |
| `timeZones` | IANA time zones of the number, such as `["Europe/Prague"]`. A number tied to an area gets that area's zone; toll free and most mobile numbers get every zone of their country. |
| `invalidReason`, `invalidReasonText` | Why a number is invalid: `TOO_SHORT`, `TOO_LONG`, `INVALID_LENGTH`, `INVALID_NUMBER` (right length, unassigned range), `INVALID_COUNTRY` (no country could be found), `NOT_A_NUMBER` or `EMPTY`, with a sentence in plain English. |
| `defaultCountry`, `datasetOffset` | The country used for numbers without +, and for numbers read from a dataset the offset of their item, starting at 0. |

### How to validate phone numbers in bulk

1. Paste the numbers into **Phone numbers**, one per line or separated by commas or semicolons. Any common format works: `+44 20 7946 0958`, `(201) 555-0123`, `0049 1512 3456789`, `1-800-FLOWERS` or `+1 202-456-1111 ext. 12`.
2. Set **Default country** to the country of numbers written without a + code, as a code (`US`, `GB`, `DE`), an English name or a calling code (`+44`). Numbers that start with + or 00 ignore it.
3. To check numbers another run collected, pick that run's dataset in **Dataset with phone numbers** and name the field in **Field with the phone number**, such as `phone` or `contact.phone`. A field with a list (`phones`) gives one row per number, and **Field with the country** can supply each item's own country.
4. Turn on **Skip duplicates** to get each number once, then click **Start**.
5. The rows appear in the **Output** tab, where you can filter on `valid` or `lineType` and download CSV, Excel or JSON. The `SUMMARY` record in the key-value store counts valid and invalid numbers, reasons, line types and countries.

Over the API, an input looks like this:

```json
{
  "phoneNumbers": ["+44 20 7946 0958", "030 901820", "0049 1512 3456789"],
  "defaultCountry": "DE",
  "skipDuplicates": true
}
```

### Example output

One row from a run on 11 October 2026. The input was a Czech mobile number in international format, so the default country (`US`) was not used.

```json
{
  "position": 6,
  "input": "+420 601 123 456",
  "defaultCountry": "US",
  "valid": true,
  "possible": true,
  "e164": "+420601123456",
  "international": "+420 601 123 456",
  "national": "601 123 456",
  "rfc3966": "tel:+420-601-123-456",
  "countryCallingCode": "420",
  "countryCode": "CZ",
  "countryName": "Czechia",
  "nationalNumber": "601123456",
  "extension": null,
  "lineType": "MOBILE",
  "carrier": "O2",
  "timeZones": [
    "Europe/Prague"
  ],
  "invalidReason": null,
  "invalidReasonText": null
}
```

### How much does it cost to validate phone numbers?

| | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| 1,000 phone numbers | $0.55 | $0.44 | $0.358 | $0.275 |

You pay only for the events in the table. There is no start fee, and compute time and proxies are included.

A list of 10,000 numbers costs $5.50 on the Free plan and $2.75 on Business. Valid and invalid numbers cost the same, because both are checked; empty lines and duplicates removed by **Skip duplicates** are not charged.

### Limits

- The check uses the numbering data of Google libphonenumber release v9.0.41 from October 2026, bundled with the actor. A range a regulator opened after that release shows as invalid until the data is updated.
- Valid means the number fits a range assigned in its country. The actor makes no network lookup (no HLR, no WhatsApp check), so it cannot say whether the number is active, reachable or who uses it.
- `carrier` is the network the range was assigned to. A number moved to another network keeps the original name. There is no carrier data for the United States, Canada and Mexico; in an October 2026 test, 93% of valid mobile numbers outside North America had one.
- In the United States and Canada mobile and fixed numbers share the same ranges, so their `lineType` is `FIXED_LINE_OR_MOBILE`.
- Time zones of numbers not tied to an area list every zone of the country: a US toll free number gets 42.
- Without **Default country**, a number written without + or 00 cannot be placed and gets `INVALID_COUNTRY`. A number starting with 00 is read as international when it is not valid as a national number of the default country.
- Speed: 10,000 numbers took 6 seconds of run time on 256 MB of memory, about 4 of them for checking and saving.
- A dataset is read through the one field you name. A label before the number (`Tel: ...`, `Call us on ...`) is skipped, and several numbers in one value, separated by commas, semicolons or `/`, give one row each. Numbers inside longer free text, such as a whole page, are not searched for.

### FAQ

#### Is it legal to validate phone numbers?

The actor checks the numbers you give it against public numbering plans and never contacts the numbers, a carrier or any other service. The numbers stay in your run's dataset and are not written to the log. Phone numbers of people are personal data in many countries, so you are responsible for having a lawful reason to process the list.

#### Does it tell me if a number is on WhatsApp or still in service?

No. Both need a live lookup with an outside service, and this actor works offline. Use the valid flag and line type to clean a list before sending it to a messaging or HLR service.

#### Why is a number I can call marked invalid?

Most often the default country is wrong for a number written without a country code, or the number has a missing or extra digit. Check `invalidReason`: `INVALID_COUNTRY` means no country could be found, `TOO_SHORT` and `TOO_LONG` point to a wrong digit count, and `INVALID_NUMBER` means the digits fall outside every assigned range in the data from October 2026.

### Related scrapers

- [EU VAT Number Validator](https://apify.com/deriverge/eu-vat-check)
- [Domain WHOIS and DNS Lookup](https://apify.com/deriverge/domain-whois-dns-lookup)

### Support

This actor is built and maintained by deriverge s.r.o., a software company based in the Czech Republic. If a run fails or a field you need is missing, please open an issue in the **Issues** tab or write to us at info@deriverge.com. We respond in English and Czech. Runs can be scheduled in Apify Console or started from the **API** tab, which has examples for Python, JavaScript and cURL and works with Make, Zapier, n8n and the Apify MCP server. If the actor saves you time, a short review helps other people find it.

# Changelog

This Actor's version history is a separate document: https://apify.com/deriverge/phone-number-validator/changelog.md

# Actor input Schema

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

One number per line, in any format: +44 20 7946 0958, (201) 555-0123, 0049 1512 3456789, 1-800-FLOWERS or with an extension such as +1 202-456-1111 ext. 12. Several numbers in one line can be separated by commas or semicolons. Numbers without a + country code are read as numbers of the default country.

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

Country used for numbers written without a + country code, as a two-letter code (US, GB, DE, IN), an English name (Germany) or a calling code (+44). Leave it empty when every number starts with + or 00.

## `datasetId` (type: `string`):

A dataset from your account, for example the output of an earlier run. Its numbers are checked after the ones in Phone numbers.

## `datasetField` (type: `string`):

Name of the field that holds the number, such as phone, phoneNumber or contact.phone for a nested field. A list of numbers (phones) or several numbers separated by commas give one row per number.

## `datasetCountryField` (type: `string`):

Optional field with each item's country (code or English name), such as countryCode. It is used instead of the default country for that item's numbers.

## `skipDuplicates` (type: `boolean`):

Return each number once. Two inputs count as the same number when they have the same E.164 form and extension, so +44 20 7946 0958 and 020 7946 0958 with default country GB are one number. Skipped duplicates are not charged.

## `maxItems` (type: `integer`):

Stop after this many numbers, so the cost of a run stays predictable. Leave it empty to check everything.

## Actor input object example

```json
{
  "phoneNumbers": [
    "(201) 555-0123",
    "+1 613-555-0123",
    "+44 20 7946 0958",
    "+49 1512 3456789",
    "+33 6 12 34 56 78",
    "+420 601 123 456",
    "+91 81234 56789",
    "+81 90-1234-5678",
    "1-800-FLOWERS",
    "12345"
  ],
  "defaultCountry": "US",
  "datasetField": "phone",
  "skipDuplicates": false
}
```

# Actor output Schema

## `numbers` (type: `string`):

One row per number: valid and possible flags, E.164, international, national and RFC 3966 formats, country, line type, original carrier, time zones and the reason when invalid.

## `summary` (type: `string`):

Counts of valid and invalid numbers, invalid reasons, line types and countries, skipped duplicates and dataset items read.

# 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": [
        "(201) 555-0123",
        "+1 613-555-0123",
        "+44 20 7946 0958",
        "+49 1512 3456789",
        "+33 6 12 34 56 78",
        "+420 601 123 456",
        "+91 81234 56789",
        "+81 90-1234-5678",
        "1-800-FLOWERS",
        "12345"
    ],
    "defaultCountry": "US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("deriverge/phone-number-validator").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": [
        "(201) 555-0123",
        "+1 613-555-0123",
        "+44 20 7946 0958",
        "+49 1512 3456789",
        "+33 6 12 34 56 78",
        "+420 601 123 456",
        "+91 81234 56789",
        "+81 90-1234-5678",
        "1-800-FLOWERS",
        "12345",
    ],
    "defaultCountry": "US",
}

# Run the Actor and wait for it to finish
run = client.actor("deriverge/phone-number-validator").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": [
    "(201) 555-0123",
    "+1 613-555-0123",
    "+44 20 7946 0958",
    "+49 1512 3456789",
    "+33 6 12 34 56 78",
    "+420 601 123 456",
    "+91 81234 56789",
    "+81 90-1234-5678",
    "1-800-FLOWERS",
    "12345"
  ],
  "defaultCountry": "US"
}' |
apify call deriverge/phone-number-validator --silent --output-dataset

```

## MCP server setup

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

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/fhW1UfvBuoQn0kuPG/builds/rePBXU8R6EIlXV21t/openapi.json
