# Phone Number Validator & Formatter | Carrier Data (`arjun_code/phone-number-validator`) Actor

Validate and format phone numbers in bulk from lists or CSV URLs with Google's libphonenumber metadata. Get E.164, country, number type, original carrier, location and time zones. Export valid and invalid results to JSON, CSV or Excel—no external lookup API or proxy required.

- **URL**: https://apify.com/arjun\_code/phone-number-validator.md
- **Developed by:** [Arjun AI](https://apify.com/arjun_code) (community)
- **Categories:** Lead generation, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 phone number records

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### Validate and format phone numbers in bulk

Phone Number Validator turns phone-number lists or CSV files into structured records ready for CRM imports, contact cleanup, reporting, and automation. Validate numbering patterns, normalize numbers to E.164, and add available country, number-type, original-carrier, location, and time-zone metadata.

Processing uses numbering-plan metadata and does not call, text, or contact a number. A valid result means the number matches known numbering rules; it does not prove that the number is assigned, active, reachable, or owned by a particular person.

### What can Phone Number Validator do?

- Validate international and national phone-number formats.
- Distinguish `valid`, `possible`, and `invalid` inputs.
- Return E.164, international, national, and RFC3966 formats.
- Classify mobile, fixed-line, VoIP, toll-free, premium-rate, and other supported number types.
- Add available country, calling-code, numbering-area, original-carrier, and time-zone metadata.
- Process an inline list, a downloadable CSV file, or both.
- Preserve invalid rows with a clear reason instead of silently dropping them.
- Export complete results as JSON, CSV, or Excel.
- Run from the Apify Console, API, schedules, integrations, or webhooks.

### How to validate phone numbers

1. Add one phone number per item under **Phone numbers**, or provide a direct CSV download URL.
2. Use `+` with the country calling code for international numbers.
3. For national numbers, set **Default region**, such as `US`, `GB`, `CN`, or `DE`.
4. Run the Actor and open **Phone validation results**.
5. Export the Dataset or connect it to your workflow.

#### International-number input

```json
{
  "phoneNumbers": [
    "+1 202 555 0100",
    "+44 20 7946 0958",
    "123"
  ],
  "language": "en"
}
```

#### National-number input

```json
{
  "phoneNumbers": [
    "202-555-0100",
    "(202) 555-0199"
  ],
  "defaultRegion": "US",
  "language": "en"
}
```

The example numbers demonstrate formatting only. They are not customer data and are not claimed to be active.

### Input parameters

| Parameter | Required | Description |
| --- | --- | --- |
| `phoneNumbers` | One input source required | Array of phone-number strings. Optional when `csvUrl` is provided. Inline entries are processed first. |
| `csvUrl` | One input source required | Direct HTTP or HTTPS URL to a UTF-8 comma-separated file with a header row. Optional when `phoneNumbers` is provided. |
| `csvColumn` | No | Exact, case-sensitive CSV header containing phone numbers. Defaults to `phone`. |
| `defaultRegion` | No | Two-letter region code used for numbers without a `+` country code. The Actor does not guess the country. |
| `maxResults` | No | Maximum number of inline and CSV entries to process. Invalid values and duplicates count toward the limit. Omit to process every selected entry. |
| `language` | No | Preferred language for country, location, and original-carrier labels. Defaults to `en`; unavailable labels fall back to available English metadata. |

Provide `phoneNumbers`, `csvUrl`, or both. When both are supplied, inline entries are processed before CSV rows. Empty CSV phone cells are skipped, while non-empty invalid entries produce a result.

For mixed-country lists, use the international `+` format. Region-specific dialing prefixes such as `00` and `011` depend on `defaultRegion`. Short codes and emergency numbers are outside this full-length phone-number validator.

#### CSV input

```json
{
  "csvUrl": "https://example.com/phones.csv",
  "csvColumn": "phone",
  "maxResults": 1000,
  "language": "en"
}
```

Replace the placeholder with a publicly downloadable CSV URL. A matching file looks like this:

```csv
phone
+44 20 7946 0958
+1 202 555 0100
```

The CSV must use UTF-8, commas, and a header row. File-sharing preview pages and login-protected URLs are not direct downloads.

### Results

The **Phone validation results** view shows the original value, validation status, E.164 number, country or region, number type, numbering area, original carrier, and validation reason. The **Formats and metadata** view adds all formats, time zones, carrier availability, and processing time.

Example result:

```json
{
  "input": "+44 20 7946 0958",
  "status": "valid",
  "valid": true,
  "possible": true,
  "reason": "",
  "e164": "+442079460958",
  "international": "+44 20 7946 0958",
  "national": "020 7946 0958",
  "rfc3966": "tel:+44-20-7946-0958",
  "extension": "",
  "countryCode": "GB",
  "countryCallingCode": 44,
  "countryName": "United Kingdom",
  "location": "London",
  "numberType": "fixed_line",
  "originalCarrier": "",
  "timeZones": ["Europe/London"],
  "carrierAvailable": false,
  "carrierLookupNote": "Original-carrier metadata is unavailable for this number range. This does not mean the number is inactive; no live carrier lookup is performed.",
  "validatedAt": "2026-09-09T15:09:37.000000+00:00"
}
```

#### Important result fields

| Field | Description |
| --- | --- |
| `status` | `valid`, `possible`, or `invalid`. |
| `valid` | Whether the number matches supported numbering-plan validation rules. |
| `possible` | Whether its length could belong to the selected numbering plan. |
| `reason` | Empty for valid numbers; otherwise a machine-readable validation reason. |
| `e164` | Normalized international number beginning with `+`. |
| `international` / `national` | Readable formatted versions. |
| `rfc3966` | Standard `tel:` URI. |
| `countryCode` / `countryName` | Detected region and localized country label. |
| `countryCallingCode` | Numeric international calling code. |
| `numberType` | Number classification such as `mobile`, `fixed_line`, or `voip`. |
| `location` | Numbering-area label, not the subscriber's live location. |
| `originalCarrier` | Available original carrier for the number range; it may differ after number portability. |
| `timeZones` | Possible time zones associated with the numbering metadata. |
| `carrierAvailable` | Whether original-carrier metadata was available. It does not indicate whether the number is active. |
| `carrierLookupNote` | Explains missing carrier metadata or a language fallback. |
| `validatedAt` | UTC processing timestamp, not a live verification time. |

Missing values are returned as `""`, not `null`. Meaningful booleans, numbers, and populated arrays retain their native types. A parseable but invalid number can still have candidate formats, so filter on `valid: true` before treating it as validated.

### Pricing

| Processed numbers | Charge |
| --- | ---: |
| 1 | $0.0005 |
| 1,000 | $0.50 |
| 10,000 | $5.00 |

Each selected phone entry successfully saved to the Dataset creates one `phone-number-processed` event. Valid, possible-only, and invalid results are billable because each is analyzed and returned. Empty CSV cells, entries skipped after the run charge limit is reached, and runs that fail before processing do not create this event.

Apify also applies its standard Actor Start charge. Review the active prices and maximum charge in Apify Console before running a large list.

### Use the API

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_API_TOKEN"])
run = client.actor("arjun_code/phone-number-validator").call(
    run_input={
        "phoneNumbers": ["+44 20 7946 0958", "+1 202 555 0100"],
        "language": "en",
    }
)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

The run's Dataset contains one row per processed entry. Its `OUTPUT` record contains totals by validation status and number type, input-selection details, billing information, and the metadata-library version.

### Frequently asked questions

#### Does valid mean the number can receive calls or SMS?

No. Validation uses numbering-plan metadata and does not contact the number or check live service.

#### Can it identify the owner or check WhatsApp registration?

No. It does not access subscriber records, names, messaging-account registration, or breach data.

#### Why is the carrier empty?

Carrier metadata is not available for every number range. `carrierAvailable: false` does not mean the number is inactive.

#### Why did a national number fail?

Set `defaultRegion` to the number's two-letter region code, or supply the international form beginning with `+`.

#### Does language translate every field?

No. It selects the best available country, location, and carrier labels. JSON keys, status values, reason codes, and formatted numbers remain unchanged.

#### Are invalid numbers omitted?

No. Invalid entries remain in the Dataset with a reason, making the Actor suitable for contact-list cleanup.

### Support and attribution

When reporting a problem, include the Apify run ID, the input format used, and a non-sensitive example that reproduces the issue. Do not publish private phone lists or API tokens.

Validation is powered by established open-source numbering metadata. Third-party attribution and license notices are retained in the Actor package.

# Actor input Schema

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

One phone number per item. Optional when csvUrl is provided. Inline entries are processed before CSV rows; invalid entries and duplicates count toward maxResults. Use + and the country code, or set defaultRegion for national numbers.

## `csvUrl` (type: `string`):

Direct HTTP or HTTPS URL to a UTF-8, comma-separated CSV with a header row. Select its phone-number column using csvColumn. Can be used alone or after phoneNumbers. Empty phone cells are skipped. The URL must be downloadable without a separate login.

## `csvColumn` (type: `string`):

Exact, case-sensitive header of the CSV column containing phone numbers. Used only with csvUrl. Other CSV columns are not included in results.

## `defaultRegion` (type: `string`):

Two-letter region code, for example CN, US, GB or DE. Applies to numbers without a + country code and to region-specific international dialing prefixes such as 00 or 011. Leave empty if every number starts with +. The Actor does not guess a country.

## `maxResults` (type: `integer`):

Maximum number of entries to validate across phoneNumbers and CSV combined, including invalid entries and duplicates. Leave empty to process all available entries. If inline entries fill the limit, the CSV is not downloaded.

## `language` (type: `string`):

Preferred language for country, area and original-carrier labels. When the selected translation is unavailable, the Actor uses an available English label; a carrier fallback is explained in carrierLookupNote. Number validation, formats, JSON field names, status values and notes are not translated.

## Actor input object example

```json
{
  "phoneNumbers": [
    "+44 20 7946 0958",
    "+1 202 555 0100"
  ],
  "csvColumn": "phone",
  "defaultRegion": "GB",
  "maxResults": 1000,
  "language": "en"
}
```

# Actor output Schema

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

One result per selected inline entry or non-empty CSV phone cell, up to maxResults. Includes invalid numbers, carrier availability and validation time. Missing values are empty strings.

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

Processed counts, validation and number-type totals, inline/CSV selection counts, result limit, input region, language, billing events and metadata library version.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("arjun_code/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 = {}

# Run the Actor and wait for it to finish
run = client.actor("arjun_code/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 '{}' |
apify call arjun_code/phone-number-validator --silent --output-dataset

```

## MCP server setup

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