CarrierLookup workflow illustration for original carrier and number portability
A visual overview of the workflow discussed in this CarrierLookup article.

The single most important sentence about a carrier lookup is also the one most often skipped: the result is the original assigned carrier. It is the carrier the number was allocated to when it was issued, not necessarily the network carrying it today.

Everything else in this article follows from that one distinction.

Portability makes "original" and "current" two different answers

In most markets a subscriber can keep a number and move it to another operator. When that happens, allocation records still show the block the number came from, while the traffic is handled somewhere else.

A carrier lookup reports the allocation. It does not observe the port. So for a ported number, the answer you get is historically correct and operationally out of date, and no amount of re-running the lookup will change that — it is not a freshness problem, it is what the data source describes.

This makes the result excellent for some jobs and unsuitable for others. Segmenting a list by originating operator, understanding the shape of a country's number space, or routing records by allocation block all work well. Deciding which network to hand a message to, or asserting that someone is reachable on a particular operator, does not.

And a carrier lookup establishes nothing at all about reachability: not by call, not by SMS, not by any messaging app, and certainly not about app registration, account activity, or marketing consent. Those are separate questions with separate answers.

Reading the fields without over-reading them

A synchronous result can carry carrier, number_type, country_code, region and city. Fields that are unavailable come back as empty strings rather than being omitted, so your parser should treat an empty string as "not supplied" and not as a meaningful value.

region and city deserve their own warning. They describe number-allocation geography — where the block was assigned — not where a person or a device is now. A number allocated in one city and carried by someone who lives on the other side of the country will still report the allocation city. Using these fields as a location signal about a person is a misreading with real consequences.

Two boolean-shaped outcomes are also routinely misread. registered: true means allocation data was found. registered: false means no allocation data was found — it is a normal result, not proof that the number is disconnected, nonexistent or invalid. In a synchronous multi-number response, each row's exists flag indicates whether that row produced a normal result; exists: false is likewise not a negative carrier conclusion.

Choosing a request shape

POST /api/v1/check performs a single check with an API key. POST /api/v1/batch-check takes 1 to 100 identifiers synchronously and returns them in input order, which matters if you are joining results back onto rows by position rather than by identifier.

Larger lists go to bulk tasks under the carrier_batch service type, which accept 1,000 to 100,000 valid numbers from a single country and are downloaded asynchronously once finished. The one-country constraint is worth designing around early: a mixed-country file is a file you will have to split.

Sources