# Phone Number Validator - Bulk E.164 Formatting & Line Type (`actor-forge/phone-number-validator`) Actor

Validate and format phone numbers in bulk, offline with Google's libphonenumber data: valid/possible, E.164, international and national formats, country, calling code, extension and line type (mobile, fixed line, toll-free, VoIP). From a list, CSV/Excel or dataset column. $0.30 per 1,000.

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

## Pricing

from $0.30 / 1,000 number validateds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 - Bulk E.164 Formatting & Line Type

Validate and format phone numbers in bulk, offline with Google's libphonenumber data: valid/possible, E.164, international and national formats, country, calling code, extension and line type (mobile, fixed line, toll-free, VoIP). From a list, CSV/Excel or dataset column. $0.30 per 1,000.

**Clean and standardise phone numbers in bulk before they hit your CRM, dialer or SMS tool.** Paste a list, or point it at a **CSV / Excel / JSON file or an Apify dataset column** (for example the output of a business-leads scrape), and get one row per number: **valid?, possible?, E.164 (+14155552671), international and national formats, tel: URI, ISO country and country name, calling code, extension and line type** (mobile, fixed line, toll-free, premium rate, VoIP, shared cost…), plus a plain-English reason when a number is invalid. Validation runs **offline against Google's libphonenumber numbering-plan data** (via libphonenumber-js), the same rules Android and Google use, so it is **fast, private and cheap**: no number is sent to any third-party service, and nothing is looked up about who owns it. Use it for **CRM and lead-list hygiene, form and signup validation, normalising numbers to E.164 for Twilio, WhatsApp Business or HubSpot, routing mobile vs landline numbers, and deduplicating contact lists**. Numbers without a + prefix use your default country, or a per-row country column. **$0.30 per 1,000 numbers**; duplicates and empty cells are free.

### What data does it return?

Every run outputs clean, schema-validated rows like these:

| input | valid | e164 | national | countryCode | lineType |
| --- | --- | --- | --- | --- | --- |
| +44 20 7946 0958 | true | +442079460958 | 020 7946 0958 | GB | fixed_line |
| (415) 555-2671 | true | +14155552671 | (415) 555-2671 | US | fixed_line_or_mobile |
| tel:+33612345678 | true | +33612345678 | 06 12 34 56 78 | FR | mobile |
| 123 | false |  |  | US |  |

### How much does it cost?

Transparent pay-per-event pricing — you only pay for what you get, and the
actor **always respects your run budget**: set a maximum total charge and it
stops cleanly at the cap instead of overrunning.

| Event | Price | Charged | Worked example |
| --- | --- | --- | --- |
| `number-validated` | $0.0003 | per unique phone number validated and delivered (valid or invalid; duplicates and empty values are free) | 10,000 CRM phone numbers = $3.00 |
| `apify-actor-start` | $0.00005 | per run per GB of memory (platform start fee) | One run at 0.5 GB = $0.000025 |

### Input options

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `phoneNumbers` | array | no | — | Phone numbers in any common format: +44 20 7946 0958, (415) 555-2671, 0049 30 1234567, tel: links, with or without extensions. Numbers without a + prefix use the default country. |
| `defaultCountry` | string | no | — | Two-letter ISO country code (US, GB, DE, FR, IN, BR…) for numbers written in national format without a + prefix. |
| `datasetId` | string | no | — | Optional. Validate a column of an Apify dataset (e.g. a leads scrape). Picking it here gives this run read access to it. Set the phone column below. |
| `fileUrl` | string | no | — | Optional. A public CSV/TSV, JSON, JSON Lines or XLSX file (first row = column names, up to 50 MB). Set the phone column below. |
| `phoneField` | string | no | — | For a dataset or file: the field / column holding the phone number (dot paths like contact.phone work). |
| `countryField` | string | no | — | For a dataset or file: a field holding each row's two-letter country code, used instead of the default country for that row. |
| `keepSourceFields` | boolean | no | `false` | For a dataset or file: copy the whole original row into sourceRow, so results can be matched back to your records. |
| `onlyValid` | boolean | no | `false` | Drop invalid numbers from the output (they are not charged). |
| `dedupe` | boolean | no | `true` | Validate each distinct number once (same digits and country); repeats are skipped and free. |
| `maxNumbers` | integer | no | `1000000` | Stop after delivering this many numbers. |

### Limits & honest notes

- Offline validation checks a number against its country's numbering plan only. It cannot tell whether a number is currently assigned, switched on or reachable, and it does not identify the carrier after number porting. "valid" means the number is correctly formed and in an allocated range.
- No lookups of people: the actor never queries who owns a number and returns no personal data beyond the number you supplied. It is meant for business uses such as CRM hygiene and form validation; process personal phone numbers only with a lawful basis.
- Line type comes from the numbering plan: in the US, Canada and some other countries mobile and fixed-line ranges overlap, so you get fixed_line_or_mobile.
- Numbering-plan data is Google's libphonenumber metadata as shipped with libphonenumber-js at build time; plans change a few times a year and the actor is rebuilt with updates.
- Files are downloaded once (up to 50 MB) and private or internal network addresses are refused at every redirect hop. Datasets are read only when you pick them in the Dataset field (limited permissions).

### Related ActorForge actors

- [Business Places Data](https://apify.com/actor-forge/business-places-data) — business leads with phone numbers to validate
- [Contact Details Scraper](https://apify.com/actor-forge/contact-details-scraper) — company phones and role emails from websites
- [Merge & Deduplicate Datasets](https://apify.com/actor-forge/dataset-merge-dedupe) — merge and dedupe lead lists

### Changelog

- **2026-10-23** — Initial release: bulk offline validation and E.164/international/national formatting with country, calling code, extension, line type and invalid reason; list, CSV/Excel/JSON file or dataset column input; per-row country column; dedupe.

***

*Built and maintained by **ActorForge**. Reliability first: every actor in the
portfolio is monitored by an automated nightly self-test, and breakages are
typically fixed the same day.*

# Actor input Schema

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

Phone numbers in any common format: +44 20 7946 0958, (415) 555-2671, 0049 30 1234567, tel: links, with or without extensions. Numbers without a + prefix use the default country.

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

Two-letter ISO country code (US, GB, DE, FR, IN, BR…) for numbers written in national format without a + prefix.

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

Optional. Validate a column of an Apify dataset (e.g. a leads scrape). Picking it here gives this run read access to it. Set the phone column below.

## `fileUrl` (type: `string`):

Optional. A public CSV/TSV, JSON, JSON Lines or XLSX file (first row = column names, up to 50 MB). Set the phone column below.

## `phoneField` (type: `string`):

For a dataset or file: the field / column holding the phone number (dot paths like contact.phone work).

## `countryField` (type: `string`):

For a dataset or file: a field holding each row's two-letter country code, used instead of the default country for that row.

## `keepSourceFields` (type: `boolean`):

For a dataset or file: copy the whole original row into sourceRow, so results can be matched back to your records.

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

Drop invalid numbers from the output (they are not charged).

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

Validate each distinct number once (same digits and country); repeats are skipped and free.

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

Stop after delivering this many numbers.

## Actor input object example

```json
{
  "phoneNumbers": [
    "+44 20 7946 0958",
    "(415) 555-2671"
  ],
  "defaultCountry": "US",
  "keepSourceFields": false,
  "onlyValid": false,
  "dedupe": true,
  "maxNumbers": 1000000
}
```

# Actor output Schema

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

One row per unique number: valid/possible, E.164, international and national formats, country, calling code, extension, line type and why it is invalid.

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

Numbers read, validated, valid and invalid, duplicates and empty values skipped, source errors and billing.

# 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": [
        "+44 20 7946 0958",
        "(415) 555-2671"
    ],
    "defaultCountry": "US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("actor-forge/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": [
        "+44 20 7946 0958",
        "(415) 555-2671",
    ],
    "defaultCountry": "US",
}

# Run the Actor and wait for it to finish
run = client.actor("actor-forge/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": [
    "+44 20 7946 0958",
    "(415) 555-2671"
  ],
  "defaultCountry": "US"
}' |
apify call actor-forge/phone-number-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,actor-forge/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/ANj4jPh1C2w51yxqv/builds/Xf8aB0lTw3tGXFyQx/openapi.json
