# MNP lookup: number portability check

> Find out whether a mobile number was ported to another network and which network (MCC/MNC) it belongs to now. Any country, real time or bulk, $0.001 per number.

Canonical: https://mobilevalidate.com/services/mnp-lookup · Last updated: 2026-09-27

![A cell tower sends signal to a SIM card; the line type is identified as mobile rather than landline or VoIP.](https://mobilevalidate.com/images/carrier-and-line-type-lookup.svg)

*Carrier lookup returns the line type (mobile, landline or VoIP) and the network behind the number.*


The MNP lookup tells you whether a mobile number has been ported to another network, and which network it belongs to now. You get `porting` (`ported` or `not_ported`), the current network code (`mcc_mnc`) and the country of that network. It works for numbers from any country, in real time and in bulk jobs, at $0.001 per conclusive answer. Unknown answers are free.

## What is mobile number portability?

Mobile number portability (MNP) lets a subscriber keep their number when they move to another mobile network. Regulators introduced it to make switching easier. The United States required it for wireless numbers from November 2003, and the EU's electronic communications code requires a port to be completed within one working day of the agreed date. Our [MNP glossary entry](/glossary/mobile-number-portability) and [portability atlas](/blog/mobile-number-portability-atlas) cover the rules country by country.

The side effect is that a number's prefix no longer tells you its network. The prefix shows which operator the range was **allocated** to. After a port, a different operator **serves** the number. Every system that guesses the network from the first digits is wrong for every ported number.

## Why does porting matter?

- **SMS routing and cost.** Many messaging routes and wholesale rates are set per destination network. Route a ported number by its prefix and the message can take a more expensive path, be rejected, or be delivered late. The current `mcc_mnc` lets you route by the network that actually serves the number.
- **Delivery analysis.** When delivery rates drop for "one operator", ported numbers are often mixed into the wrong bucket. Grouping by the current network gives you honest per-network numbers.
- **Fraud checks.** In a port-out scam, a criminal moves a victim's number to a network and SIM they control, then receives the victim's one-time passcodes. A number that shows `ported` when your records say it wasn't, or a current network that differs from the one you stored at sign-up, is a reason to add a step before a password reset or payout.
- **Data quality.** Customer records often store the operator a number was bought from. Refreshing it with the current network keeps segmentation and support routing right.

A port by itself is not a risk signal. Millions of people switch operators. Treat `ported` as context, and act on a *change* compared with what you knew before.

## MNP lookup or HLR lookup?

| | MNP lookup (`mnp`) | [HLR lookup](/services/hlr-lookup) (`hlr`) |
|---|---|---|
| Question it answers | Was the number ported, and which network is it on now? | Is the phone reachable right now, and on which network? |
| Porting | `porting`: `ported`, `not_ported` | `ported`: `true` / `false` |
| Current network | `mcc_mnc`, `country` | `network`, `mcc_mnc`, `country` |
| Live reachability | No | `status`: `reachable`, `unreachable`, `invalid` |
| Roaming | No | `roaming`: `true` / `false` |
| Price at launch | $0.001 per number | $0.005 per number |
| Typical use | Routing, least-cost messaging, record refresh, port-change checks | OTP pre-checks, cleaning lists of possibly disconnected numbers |

If you need the network for routing, the MNP lookup is enough. If you also need to know whether the phone is switched on or the number is still assigned, use the HLR lookup, which includes the porting answer. There is no need to run both on the same number. The [carrier lookup](/services/carrier-lookup) answers a third question, the line type (mobile, landline, VoIP).

## What do you get back?

| Field | Type | Meaning |
|---|---|---|
| `attributes.porting` | enum | `ported`, `not_ported` or `unknown` (primary answer) |
| `attributes.mcc_mnc` | string | Code of the network the number belongs to now ([MCC + MNC](/glossary/mcc-mnc)) |
| `attributes.country` | string | ISO 3166-1 alpha-2 country of that network |
| `registered` | boolean or null | `true` when the answer is conclusive; `null` when not |
| `status` / `reason` | enum / string | `completed`, `pending`, `unknown` (e.g. `UPSTREAM_TIMEOUT`), `unsupported_country` |
| `checked_at`, `cached`, `billed` | — | When the answer was obtained, whether it came from cache, whether it was charged |

The MNP lookup returns no subscriber data: no name, no SIM identifiers, no location. It describes where the number is routed, not who holds it.

## How is it billed?

$0.001 per number at launch, for real-time lookups and bulk jobs alike. The [pricing](/pricing) page shows the current price. `ported` and `not_ported` are conclusive answers and are billed. You're not charged for inconclusive results (unknown, unsupported country, timeout, invalid, duplicate). A number that the lookup can't place on any network, for example an invalid or unassigned number, comes back as `unknown` and is free.

Repeat checks of the same number inside the freshness window can come from your account's cache and are free (`cached: true, billed: false`). Send `max_age: 0` to force a fresh check, for example right before a sensitive account change.

## What are the limits?

- Built for mobile numbers, in every country except [sanctioned countries and regions](/docs/services#which-countries-are-never-checked), which answer `unsupported_country` for free.
- Up to 100 numbers per real-time lookup and 50,000 per job, and up to 20 checks per request.
- Requests that look like sequential number ranges or generated e-mail lists are rejected (`suspected_enumeration`).
- A check can come back as `pending` first when a network answers slowly. Poll the lookup, or use a bulk job.
- The answer describes the number at the time of the check. Numbers can be ported again later, so refresh stored results before decisions that depend on them.

## How do you use it responsibly?

Porting data describes a person's phone number. Check only numbers you have a lawful reason to process, such as customers, sign-ups and contacts who gave you their number. Don't use it to profile people or for eligibility decisions like credit, housing or employment. The [acceptable use policy](/legal/acceptable-use) applies, and people can object to checks of their number through the [opt-out form](/opt-out).

## Example request

With a test key, `+447700900001` returns `not_ported`, `…006` returns `ported`, `…003` returns `unknown`, `…004` is `pending` and then `not_ported`, and `…005` returns `unsupported_country`. See [test mode](/docs/test-mode).

```bash
curl https://api.mobilevalidate.com/v1/lookup \
  -H "Authorization: Bearer $MOBILEVALIDATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"numbers": ["+447700900006"], "checks": ["mnp"]}'
```

Response (excerpt, test mode: the first item of `results`):

```json
{
  "kind": "phone",
  "input": "+447700900006",
  "e164": "+447700900006",
  "country": "GB",
  "number_status": "valid",
  "checks": {
    "number.mnp": {
      "service": "number.mnp",
      "status": "completed",
      "registered": true,
      "attributes": {
        "porting": "ported",
        "mcc_mnc": "23410",
        "country": "GB"
      },
      "confidence": "high",
      "confidence_score": 0.99,
      "checked_at": "2026-09-27T09:12:04.318Z",
      "cached": false,
      "age_seconds": 0,
      "billed": false,
      "reason": null,
      "poll_after_ms": null
    }
  },
  "test": true
}
```

In live mode, `billed` is `true` for this answer. Routing by the current network, and flagging a network change against what you stored:

```js
const mnp = result.checks["number.mnp"];
if (mnp.status === "completed") {
  const route = routeFor(mnp.attributes.mcc_mnc); // your per-network routing table
  if (stored.mcc_mnc && stored.mcc_mnc !== mnp.attributes.mcc_mnc) {
    // the number moved since you last checked: add a step before a password reset or payout
  }
} else {
  // unknown, pending or unsupported_country: not billed; fall back to your default route
}
```

## Frequently asked questions

### What is an MNP lookup?

A check that tells you whether a mobile number has been ported away from the network its number range was allocated to, and which network it belongs to now, as an MCC/MNC code and a country. MNP stands for mobile number portability.

### What does an MNP lookup cost?

$0.001 per number, in real time and in bulk jobs. ported and not_ported are conclusive answers and are billed. unknown is free, including numbers the lookup can't place on a network. The pricing page always shows the current price.

### What is the difference between an MNP lookup and an HLR lookup?

The MNP lookup answers two questions: was the number ported, and which network is it on now. The HLR lookup asks the home network live and adds whether the phone is reachable right now and whether it is roaming. MNP is enough for routing; HLR is for reachability.

### Does it tell me when the number was ported?

No. It returns ported or not_ported and the current network, not a porting date. A port on its own is normal: many people switch operators every year.

### Which countries does it cover?

Mobile numbers from any country, except sanctioned countries and regions, which are never checked and never billed. When no conclusive answer is available for a number, the result is unknown and free.

### Does it work for landlines?

It is built for mobile numbers. Use the carrier lookup to learn the line type first if your list mixes landlines, VoIP and mobiles.

## Service code and modes

- Code: `number.mnp` (input: phone number)
- Modes: realtime and bulk · worldwide

## Price (live)

- Realtime (POST /v1/lookup): $0.001 per check ($1.00 per 1,000)
- Bulk (POST /v1/jobs): $0.001 per check ($1.00 per 1,000)
- You're not charged for inconclusive results (unknown, unsupported country, timeout, invalid, duplicate).

## Response fields (from the public catalog)

| Field | Type | Meaning |
|---|---|---|
| registered | boolean or null | true when data was found; null when unknown (not charged) |
| status | enum | completed, pending, unknown, unsupported_country, failed |
| checked_at | timestamp | When the answer was obtained |
| attributes.porting | enum (ported, not_ported, unknown) | Ported to another network or not. |
| attributes.mcc_mnc | string | Current network code (MCC+MNC). |
| attributes.country | string | ISO country of the current network. |
