# Bulk Phone Number Validator - Line Type, Carrier & E.164 Format (`flash_scraper/phone-number-validator`) Actor

Validate, format & classify phone numbers in bulk with Google's libphonenumber. Per number: valid/invalid, E.164 + national + international formats, country, calling code, line type (mobile/landline/VoIP/toll-free) & carrier. Clean lists before you dial. No API key, no proxies, no network.

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

## Pricing

from $0.35 / 1,000 phone validateds

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/platform/actors/running/actors-in-store#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

## Phone Number Validator — validate phone numbers in bulk with line type, country & carrier

**Validate phone numbers in bulk** before you call, text, or import them into your CRM. Paste a list of numbers in any format — international, local, messy copy-paste — and get back a clean dataset: valid or not, normalized **E.164 / national / international** formats, **country**, **line type** (mobile, fixed line, VoIP, toll-free…), and best-effort **carrier**. Every check runs **fully offline** against Google's libphonenumber metadata: **no API key, no network calls, no proxies**, and pay-per-result pricing so you're only charged for numbers actually processed.

### What it does

- **Validates each number** with Google's libphonenumber — the same library that powers Android's dialer — returning both a strict `valid` flag and a looser `possible` flag.
- **Normalizes every valid number into three formats**: E.164 (`+14155550132`), international (`+1 415-555-0132`), and national (`(415) 555-0132`), so your dialer, SMS gateway, and CRM all get the format they expect.
- **Classifies the line type** — `mobile`, `fixed_line`, `fixed_line_or_mobile`, `voip`, `toll_free`, `premium_rate`, `shared_cost`, `pager`, and more — so you can skip landlines in an SMS campaign or flag premium-rate traps.
- **Identifies the country and location**: the country name (`United States`, `Morocco`), a human-readable locality/region description (`San Francisco, CA`) where available, the ISO region code (`US`, `MA`, `GB`), and the country calling code.
- **Looks up the carrier** (best-effort, from libphonenumber's carrier metadata) where available.
- **Parses local numbers** without a `+` prefix using a `defaultRegion` you choose, so `020 7946 0958` parses correctly as a UK number.
- **Deduplicates input** before validating (on by default) and can optionally **drop invalid numbers** from the output so the dataset is import-ready.
- Handles input as a string list or a single string separated by newlines, commas, or semicolons.

Because everything runs locally against bundled metadata, runs are fast and deterministic — no rate limits, no third-party phone-validation API bills, no data sent to external services.

### Use cases

- **Sales prospecting** — clean the phone column of a scraped lead list before handing it to SDRs, so nobody wastes dials on numbers that were never valid.
- **SMS campaign prep** — filter to `number_type = mobile` and drop landlines, VoIP, and toll-free numbers that can't receive texts, protecting your sender reputation and per-message spend.
- **CRM hygiene** — normalize every contact to E.164 so HubSpot, Salesforce, or your dialer stops choking on `(0)6-12 34 56 78`-style formatting, and dedupe contacts that are the same number written two ways.
- **Agency deliverables** — if you sell lead lists on Fiverr or Upwork, run every list through the validator and ship a `valid` column plus proper formatting as part of your quality guarantee.
- **Call-center routing & compliance** — split lists by country and region code to route to the right team, and flag `premium_rate` numbers before your auto-dialer ever touches them.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `phones` | array | *(required)* | Phone numbers to validate, one per line. International (`+1...`) or local numbers (set the default region for local ones). |
| `defaultRegion` | string | `"US"` | Two-letter country code used to parse local numbers without a `+` prefix (e.g. `US`, `MA`, `FR`, `GB`). |
| `onlyValid` | boolean | `false` | Keep only numbers that pass full validation. |
| `dedupe` | boolean | `true` | Drop duplicate inputs before validating. |

Example input:

```json
{
  "phones": ["+1 415 555 0132", "+212 661-234567", "020 7946 0958", "not a phone"],
  "defaultRegion": "US",
  "onlyValid": false,
  "dedupe": true
}
```

Only `phones` is required. `phones` also accepts a single string separated by newlines, commas, or semicolons.

### Output

Each dataset row is one validated number:

| Field | Description |
|---|---|
| `input` | The raw number exactly as you provided it |
| `valid` | `true` if the number is fully valid for its region |
| `possible` | `true` if the number has a plausible length/structure (looser check) |
| `e164` | Normalized E.164 format (`+14155550132`) |
| `international` / `national` | International and national display formats |
| `country` | Country name derived from the region code (`United States`, `Morocco`, `United Kingdom`) |
| `location` | Human-readable locality / region description (`San Francisco, CA`) where libphonenumber has geo metadata |
| `region_code` | ISO region code (`US`, `GB`, `MA`) |
| `country_code` | Numeric calling code (`1`, `44`, `212`) |
| `number_type` | `mobile`, `fixed_line`, `fixed_line_or_mobile`, `voip`, `toll_free`, `premium_rate`, … |
| `carrier` | Carrier name where metadata exists (best-effort) |
| `status` | `valid`, `possible_but_invalid`, `invalid`, or `parse_error:<reason>` |

Example row:

```json
{
  "input": "+212 661-234567",
  "valid": true,
  "possible": true,
  "e164": "+212661234567",
  "international": "+212 661-234567",
  "national": "0661-234567",
  "country": "Morocco",
  "location": "Morocco",
  "region_code": "MA",
  "country_code": 212,
  "number_type": "mobile",
  "carrier": "IAM",
  "status": "valid"
}
```

Export the dataset to **CSV, Excel, or JSON** straight from the Apify Console, or pull it via the API.

#### Example output

A real sample from a live run:

| input | valid | country | location | number\_type | carrier |
|---|---|---|---|---|---|
| +1 415 555 0132 | true | United States | San Francisco, CA | fixed\_line\_or\_mobile |  |
| +212 661-234567 | true | Morocco |  | mobile | Maroc Telecom |
| +44 20 7946 0958 | true | United Kingdom | London | fixed\_line |  |
| not a phone | false |  |  |  |  |

### Pricing

This actor uses **pay-per-result pricing**: you're charged only per number that actually lands in your dataset — a fraction of a cent per validated row. No subscription, no minimum, no charge for failed runs. A **free Apify plan** includes enough platform credit to validate thousands of numbers, so you can clean a real list before spending anything.

### Tips / FAQ

#### Does "valid" mean the number is currently in service?

No. Validation is **structural**: the number matches the official numbering plan for its country (right length, real prefix, assigned range). It cannot tell whether a specific line is currently active or answered — that would require a live carrier (HLR) lookup, which this actor deliberately doesn't do. It reliably catches typos, fake numbers, wrong lengths, and impossible prefixes.

#### How accurate is the carrier field?

Best-effort. Carrier names come from libphonenumber's metadata and reflect the carrier the number range was **originally assigned to**. Ported numbers may show the old carrier, and many ranges (especially US fixed lines) have no carrier metadata at all — you'll get `null` there.

#### What happens to numbers that can't be parsed?

They still get a row (unless `onlyValid` is on) with `valid: false` and a `status` like `parse_error:1` explaining why parsing failed, so you can audit exactly which inputs were rejected and fix them upstream.

#### Is there a limit on list size?

No hard limit in the actor. Validation is offline and fast, so even lists with tens of thousands of numbers run quickly. `dedupe` (on by default) keeps you from paying twice for the same number pasted twice.

#### Do I need proxies or an API key?

No. The actor makes **zero network requests** — every check runs locally against bundled metadata, so there's nothing to block, rate-limit, or subscribe to.

#### How do I automate this?

Call the actor from the [Apify API](https://docs.apify.com/api/v2) with your list in the `phones` field, or put it on an Apify **Schedule** to re-validate your CRM export weekly. The dataset is available as CSV/JSON/Excel the moment the run finishes, and you can wire it to Zapier/Make via Apify integrations.

### Related actors

- [Bulk Email Verifier](https://apify.com/flash_scraper/email-verifier) — the email counterpart: verify and score email addresses before you hit send.
- [Email Pattern Finder](https://apify.com/flash_scraper/email-pattern-finder) — guess likely work emails from a name + company domain.
- [Company & Domain Enricher](https://apify.com/flash_scraper/company-domain-enricher) — turn a domain list into full company records with emails, socials, and tech stack.

***

Found a bug or missing a feature? Open an issue on this actor's **Issues tab** — typical response within 1 business day.

# Actor input Schema

## `phones` (type: `array`):

Phone numbers to validate, one per line. International (+1...) or local numbers (set the default region for local ones).

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

Two-letter country code used to parse local numbers without a + prefix (e.g. 'US', 'MA', 'FR', 'GB').

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

Keep only numbers that pass full validation.

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

Drop duplicate inputs before validating.

## Actor input object example

```json
{
  "phones": [
    "+1 415 555 0132",
    "+212 661-234567",
    "+44 20 7946 0958",
    "not a phone"
  ],
  "defaultRegion": "US",
  "onlyValid": false,
  "dedupe": true
}
```

# Actor output Schema

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

No description

# 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 = {
    "phones": [
        "+1 415 555 0132",
        "+212 661-234567",
        "+44 20 7946 0958",
        "not a phone"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("flash_scraper/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 = { "phones": [
        "+1 415 555 0132",
        "+212 661-234567",
        "+44 20 7946 0958",
        "not a phone",
    ] }

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

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

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

```

## CLI example

```bash
echo '{
  "phones": [
    "+1 415 555 0132",
    "+212 661-234567",
    "+44 20 7946 0958",
    "not a phone"
  ]
}' |
apify call flash_scraper/phone-number-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=flash_scraper/phone-number-validator",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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