# International Phone Validator - Free Beta (`rex-law/international-phone-validator-free-beta`) Actor

Validate, classify, deduplicate, and format up to 1,000 international phone numbers offline with bundled libphonenumber metadata.

- **URL**: https://apify.com/rex-law/international-phone-validator-free-beta.md
- **Developed by:** [Rex Law](https://apify.com/rex-law) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## International Phone Validator - Free Beta

Validate, normalize, classify, and deduplicate up to 1,000 phone numbers per run. The Actor uses the pinned `libphonenumber-js/max` metadata package entirely inside its container. An Actor run makes **zero outbound network requests** and needs no external API, API key, login, cookie, proxy, or target website.

The package installation happens when the image is built. After that, validation is deterministic for the metadata version bundled in that image. The Docker smoke runs the finished image with `--network=none` to prove that the runtime path has no network dependency.

### Input

```json
{
  "phoneNumbers": [
    "+1 202-555-0123",
    "(202) 555-0123",
    "+44 20 7946 0018",
    "+33 1 23 45 67 89",
    "123"
  ],
  "defaultCountry": "US"
}
````

- `phoneNumbers` is required and must contain 1-1,000 strings.
- Each string is limited to 120 characters; the maximum raw input payload represented by phone strings is therefore bounded at 120,000 characters.
- International numbers should start with `+` and their country calling code.
- `defaultCountry` is optional. It must be a supported two-letter ISO 3166-1 code and is used only when an input does not contain an international calling code.
- Unknown top-level fields, unsupported default countries, non-string items, oversized items, and arrays outside the hard limit fail before processing.
- Malformed or invalid phone-number strings inside an otherwise valid request produce their own dataset rows and stable error codes. They do not discard other results.

### Deduplication

Parsed numbers are deduplicated by E.164, so `+1 202-555-0123`, `(202) 555-0123`, and `202.555.0123` with `defaultCountry: "US"` produce one result. The first input and its zero-based `inputIndex` remain the primary row. Later matches appear in `duplicateInputs`, and `duplicateCount` reports how many were removed.

Inputs that cannot be parsed do not have an E.164 identity. Those are deduplicated only when their whitespace-trimmed input text is identical. Output is strictly bounded at 1,000 rows.

### Dataset output

```json
{
  "type": "phone_validation",
  "inputIndex": 0,
  "input": "+1 202-555-0123",
  "valid": true,
  "possible": true,
  "e164": "+12025550123",
  "internationalFormat": "+1 202 555 0123",
  "nationalFormat": "(202) 555-0123",
  "country": "US",
  "callingCode": "+1",
  "numberType": "FIXED_LINE_OR_MOBILE",
  "duplicateCount": 1,
  "duplicateInputs": [
    {
      "inputIndex": 1,
      "input": "(202) 555-0123"
    }
  ],
  "error": null,
  "checkedAt": "2026-07-18T12:00:00.000Z"
}
```

Every row always contains every documented field. Fields that cannot be derived are `null`; they are never guessed. `country` is the ISO alpha-2 numbering-plan country when the metadata can identify one. `numberType` can be `FIXED_LINE`, `MOBILE`, `FIXED_LINE_OR_MOBILE`, `TOLL_FREE`, `PREMIUM_RATE`, `SHARED_COST`, `VOIP`, `PERSONAL_NUMBER`, `PAGER`, `UAN`, `VOICEMAIL`, or `null`.

An invalid row includes a structured error:

```json
{
  "input": "123",
  "valid": false,
  "possible": false,
  "e164": "+1123",
  "error": {
    "code": "TOO_SHORT",
    "message": "The number is too short for the applicable numbering plan."
  }
}
```

Stable error codes are `EMPTY_INPUT`, `INVALID_CHARACTERS`, `NOT_A_NUMBER`, `INVALID_COUNTRY`, `TOO_SHORT`, `TOO_LONG`, `INVALID_LENGTH`, `IMPOSSIBLE_NUMBER`, and `INVALID_NUMBER`.

### Structured summary

The `OUTPUT` key-value record contains a bounded summary rather than phone-number data:

```json
{
  "type": "phone_validation_summary",
  "status": "completed_with_errors",
  "defaultCountry": "US",
  "inputsReceived": 5,
  "uniqueNumbers": 4,
  "duplicatesRemoved": 1,
  "resultsReturned": 4,
  "uniqueValidNumbers": 3,
  "uniqueInvalidNumbers": 1,
  "uniquePossibleNumbers": 3,
  "uniqueImpossibleNumbers": 1,
  "uniqueErrorsByCode": {
    "TOO_SHORT": 1
  },
  "deduplication": "E164_THEN_TRIMMED_INPUT",
  "engine": {
    "library": "libphonenumber-js",
    "version": "1.13.9",
    "metadata": "max",
    "networkRequests": 0
  },
  "limits": {
    "maxInputs": 1000,
    "maxResults": 1000,
    "maxCharactersPerInput": 120
  }
}
```

`status` is `success` only when every unique result is valid. It is `completed_with_errors` when one or more rows are invalid or unparseable. Per-item validation failures are expected data outcomes, so even an all-invalid batch completes and returns all bounded error rows. Invalid top-level input still fails the run closed.

### Capability boundary

`possible` means the digit count is possible for the numbering plan in the bundled metadata. `valid` means the number pattern is valid under that same metadata. Neither value proves that a number:

- has been assigned;
- is currently active or reachable;
- can receive calls, SMS, or messaging-app traffic;
- belongs to any person or organization;
- uses a particular carrier;
- is located where the country or calling code suggests at validation time.

This Actor does **not** perform carrier lookup, subscriber or real-name lookup, HLR lookup, line reachability tests, live calling, SMS verification, geolocation, or data-broker enrichment. It does not claim those capabilities in output or logs.

Phone numbers can be personal data. The Actor does not transmit them to a third party, and logs contain counts only. Inputs and results are still stored in the run's Apify storage according to the user's Apify account settings and retention policy; callers remain responsible for lawful handling and deletion.

### Local verification

Requires Node.js 22 or newer.

```sh
npm ci
npm test
npm run check
npm run smoke
```

The deterministic local smoke executes the full Actor entrypoint against five fixed inputs. It expects three valid unique numbers, one invalid number, and one E.164 duplicate.

### Docker offline smoke

Docker must be running:

```sh
npm run smoke:docker
```

The script builds the release image, runs the same fixed Actor input with Docker networking disabled, reads the dataset and `OUTPUT` record from a temporary local Apify store, and validates every expected count and representative field.

### Fail-closed FREE/LIMITED release

Local release validation makes no external request and changes no state:

```sh
npm run release -- --validate-only
```

The exact intentional publication command is:

```sh
CONFIRM_PUBLISH_FREE_BETA=international-phone-validator-free-beta npm run release
```

The real release path is deliberately gated. It creates or updates the beta while private, enforces `LIMITED_PERMISSIONS`, refuses to overwrite an already-public beta, uploads the pinned source, waits for a successful build, and runs a fixed five-number private-cloud smoke. The smoke is offline with respect to phone data: it uses only bundled metadata and asserts `networkRequests: 0`. Only after the smoke and a second private/FREE check does the workflow change `isPublic`.

The release workflow never creates or modifies pricing configuration. It rejects any non-FREE state it can observe, scans every outbound request body for the forbidden pricing field, and attempts to return the Actor to private if final publication verification fails. Any failed build, smoke, permission, privacy, or FREE-state gate stops publication.

Do not run the intentional publication command unless a public Apify release is desired. This repository verification did not call the Apify API and did not publish anything.

### Maintenance

Phone numbering plans change. Upgrade `libphonenumber-js` deliberately, review its metadata and changelog, regenerate the lockfile, rerun all unit and offline smoke tests, and publish a new build only after the same gates pass. Results should always be interpreted against the metadata version in the deployed image.

# Actor input Schema

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

International numbers should begin with +. National-format numbers require defaultCountry. Duplicate numbers that resolve to the same E.164 value are returned once.

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

Two-letter ISO 3166-1 code used only for numbers without an international + calling code, for example US, GB, DE, SG, or MY.

## Actor input object example

```json
{
  "phoneNumbers": [
    "+1 202-555-0123",
    "+44 20 7946 0018",
    "+33 1 23 45 67 89"
  ]
}
```

# Actor output Schema

## `validations` (type: `string`):

One row per unique E.164 number, or per unique unparseable trimmed input. Duplicate inputs are attached to the first row.

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

Input, unique-result, duplicate, validity, possibility, error-code, engine, and hard-limit counts.

# 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("rex-law/international-phone-validator-free-beta").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("rex-law/international-phone-validator-free-beta").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 '{}' |
apify call rex-law/international-phone-validator-free-beta --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "International Phone Validator - Free Beta",
        "description": "Validate, classify, deduplicate, and format up to 1,000 international phone numbers offline with bundled libphonenumber metadata.",
        "version": "0.1",
        "x-build-id": "ZZdYdukhkJsjCkGfI"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/rex-law~international-phone-validator-free-beta/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-rex-law-international-phone-validator-free-beta",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/rex-law~international-phone-validator-free-beta/runs": {
            "post": {
                "operationId": "runs-sync-rex-law-international-phone-validator-free-beta",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/rex-law~international-phone-validator-free-beta/run-sync": {
            "post": {
                "operationId": "run-sync-rex-law-international-phone-validator-free-beta",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "phoneNumbers"
                ],
                "properties": {
                    "phoneNumbers": {
                        "title": "Phone numbers",
                        "minItems": 1,
                        "maxItems": 1000,
                        "type": "array",
                        "description": "International numbers should begin with +. National-format numbers require defaultCountry. Duplicate numbers that resolve to the same E.164 value are returned once.",
                        "items": {
                            "type": "string",
                            "maxLength": 120
                        },
                        "default": [
                            "+1 202-555-0123",
                            "+44 20 7946 0018",
                            "+33 1 23 45 67 89"
                        ]
                    },
                    "defaultCountry": {
                        "title": "Default country (optional)",
                        "pattern": "^[A-Za-z]{2}$",
                        "minLength": 2,
                        "maxLength": 2,
                        "type": "string",
                        "description": "Two-letter ISO 3166-1 code used only for numbers without an international + calling code, for example US, GB, DE, SG, or MY."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
