# Bulk Phone Carrier & Line Type Checker | LookupLab (`pale_firewood/lookuplab-phone-list-checker`) Actor

Bulk phone carrier and mobile/landline/VoIP checks for up to 1,000 numbers. Bring your LookupLab API key, keep row order, and export CSV or JSON. Includes a synthetic demo. LookupLab credits apply.

- **URL**: https://apify.com/pale_firewood/lookuplab-phone-list-checker.md
- **Developed by:** [Clement Horak](https://apify.com/pale_firewood) (community)
- **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/actors/running/actors-in-store.md#pay-per-usage

## 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

## Bulk Phone Carrier & Line Type Checker

Check a phone list before routing leads or preparing an outreach workflow. LookupLab returns phone validity signals, carrier, country, mobile/landline/VoIP classification, and portability information when available. Export the results as CSV, JSON, or Excel from the Apify dataset.

**Current release: use your own LookupLab API key, or try the synthetic demo.** There is no Actor fee; normal Apify platform usage and your LookupLab credit usage apply. Get your key from [LookupLab](https://lookuplab.io/signup?utm_source=apify\&utm_medium=marketplace\&utm_campaign=phone-list-checker).

### Choose a mode

| Mode | What it does | Lookup billing |
| --- | --- | --- |
| Demo | Shows clearly labeled synthetic output for up to three numbers. Does not query any phone data. | No lookup event. Normal Apify platform usage applies. |
| Own key | Checks numbers against your existing LookupLab account. Enter the key using the secret input field. | No lookup event through Apify. LookupLab credits and normal Apify platform usage apply. |

Managed billing through Apify is not enabled in this release. A future edition may offer it after billing configuration and pricing verification. This release never consumes a publisher-owned LookupLab key.

### Input

Paste numbers into the input list, or start the Actor through Apify's API:

```json
{
  "mode": "own-key",
  "lookupLabApiKey": "YOUR_LOOKUPLAB_KEY",
  "numbers": ["+12025550123", "+442079460123"]
}
```

These examples use fictional numbers and do not promise a valid lookup result. Include `+` and the country code. Spaces, parentheses, and hyphens are allowed. National numbers without a country code are rejected rather than guessed. This version accepts a JSON/string list; convert a CSV's phone column into that list before running. CSV **output** is available from the dataset export menu. Maximum 1,000 input rows per run. Duplicate input numbers stay as distinct rows and can each spend LookupLab credits.

For own-key mode add `"lookupLabApiKey": "YOUR_KEY"` using the encrypted secret field in the Console. Never publish real keys in examples or workflow files.

### Output

Each completed or locally rejected row contains:

- Original row number and input, plus a stable `row_id`.
- `status`: `complete`, `lookup_error`, `invalid_format`, or `demo`.
- `charged`: whether an Apify lookup event was confirmed. This does not report LookupLab credit usage in own-key mode.
- `valid`, normalized `number`, `national_format`, `country`, `carrier`, `line_type`, `ported`, and a safe error description.

Unavailable fields are `null`. Results exclude caller names, account balances, API keys, and unrelated provider data. A valid or mobile signal does **not** establish ownership, consent, deliverability, or permission to call/text. Coverage and carrier classification vary by country and data availability. This Actor does not verify SMS opt-in or screen Do Not Call lists.

Rejected input that resembles a spreadsheet formula is prefixed with an apostrophe in the dataset for safer CSV/Excel export. Its original text remains in the per-row receipt.

### Interrupted runs and spending limits

Processing is sequential. The Actor checks the spending limit before every managed lookup and leaves a small amount unused to avoid an automatic platform abort during the final paid call. If billing cannot be confirmed, no new lookup is performed. If a provider request times out or billing acknowledgement is lost, the Actor stops and keeps prior results and per-row receipts in the run's key-value store (`ROW-000001`, etc.).

**Resurrect the same run with unchanged input and credential within 23 hours.** The Actor reuses stable billing and LookupLab idempotency keys. It does not automatically retry uncertain requests or start replacement runs. Older interrupted work needs support reconciliation because upstream idempotency retention is limited. Changing a number, mode, or API credential requires a new run and can incur new charges.

Dataset writes are append-only. Recovery checks existing `row_id` values; a transport-level dataset retry can still duplicate an output row. Deduplicate exports by `row_id` if needed. Key-value receipts are the recovery source of truth. This does not create a second lookup charge.

### Privacy and support

Submit only phone data you are authorized to process. The Actor sends each phone number to LookupLab, which uses its lookup provider to return the requested signals. Inputs, result rows, and receipts are stored in your Apify run according to Apify retention settings. Manage access and deletion in your Apify account. Refer to [LookupLab privacy](https://lookuplab.io/privacy) and [support](https://lookuplab.io/contact) for service handling and questions. Do not include names, messages, or other customer records in the phone number field.

### Local development

Node.js 22 or later:

```sh
npm ci --ignore-scripts
npm test
```

For a real SDK smoke run, put `{ "mode": "demo", "numbers": ["+12025550123", "invalid"] }` in `storage/key_value_stores/default/INPUT.json`, then run `npm start`. Local managed mode always fails closed. Own-key mode can run locally and spends the supplied account's credits. No paid API calls are needed for tests.

This directory is self-contained. Publish only these files in a separate public connector repository. Never publish the private LookupLab application repository, environment files, storage, or credentials.

# Actor input Schema

## `mode` (type: `string`):

Demo shows synthetic output without a lookup. Own key spends your existing LookupLab credits. Managed Apify billing is not enabled in this release.

## `numbers` (type: `array`):

Include + and country code. Up to 1,000 numbers per run; demo maximum 3. Malformed rows are preserved and skipped without lookup charges. Repeated numbers remain separate rows.

## `lookupLabApiKey` (type: `string`):

Your LookupLab account is charged for successful lookups in own-key mode. Leave empty for demo or managed mode. Stored as an encrypted input secret.

## Actor input object example

```json
{
  "mode": "demo",
  "numbers": [
    "+12025550123",
    "+442079460123"
  ]
}
```

# 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 = {
    "numbers": [
        "+12025550123",
        "+442079460123"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pale_firewood/lookuplab-phone-list-checker").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 = { "numbers": [
        "+12025550123",
        "+442079460123",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("pale_firewood/lookuplab-phone-list-checker").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 '{
  "numbers": [
    "+12025550123",
    "+442079460123"
  ]
}' |
apify call pale_firewood/lookuplab-phone-list-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pale_firewood/lookuplab-phone-list-checker"
        }
    }
}
```

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/X8mwMVb50ui9ThIbE/builds/Nb0gM1ehSRp69cZi0/openapi.json
