API Documentation
A single REST API over 3,042 mobile networks in 227 countries: look up any PLMN (MCC + MNC), search by country, operator or brand, and resolve phone numbers to their country's operators. The service is free — you only need an API key.
Base URL: https://mcc-mnc.dev/api/v1 · All endpoints are
GET · CORS is open (Access-Control-Allow-Origin: *,
preflight OPTIONS returns 204).
Quickstart
- Sign in with your e-mail and create a key on the dashboard. Keys look like
mcc_…. - Send it in the
X-API-Keyheader:
curl -H "X-API-Key: mcc_your_key" \
https://mcc-mnc.dev/api/v1/plmn/23002 Response — a single flat Row object:
{
"plmn": "23002",
"mcc": "230",
"mnc": "02",
"country": "Czech Republic",
"iso2": "CZ",
"iso3": "CZE",
"iso_numeric": "203",
"dial_prefix": "+420",
"brand": "O2",
"operator": "O2 Czech Republic",
"status": "Operational",
"type": "National",
"bands": "GSM 900 / GSM 1800 / LTE 800 / LTE 1800 / LTE 2600 / TD-LTE 2600 / 5G 3500",
"technology": [
"GSM -900/1800 MHz ( GPRS , EDGE )",
"700/800/900/1800/2100/2600 MHz LTE , LTE-A , VoLTE , VoWiFi",
"700/1800/2100 ( Prague Metro only) /3500 MHz 5G NR"
],
"ownership": "PPF",
"subscribers": 5.987,
"subscribers_as_of": "2021-Q2",
"market_reach": 37.1,
"market_reach_basis": "country_total",
"rank": 2,
"notes": "Former Eurotel; CDMA 450 shut down June 2019; UMTS shut down Nov 2021"
} Authentication
Every endpoint requires an API key. Pass it as X-API-Key: mcc_… or,
equivalently, Authorization: Bearer mcc_….
# Preferred header
curl -H "X-API-Key: mcc_your_key" "https://mcc-mnc.dev/api/v1/search?q=230"
# Bearer alias — identical behaviour
curl -H "Authorization: Bearer mcc_your_key" "https://mcc-mnc.dev/api/v1/search?q=230"
A missing header yields 401 missing_api_key; an unknown or revoked key yields
401 invalid_api_key. Keys are free and self-service —
create one here, and revoke or rotate them any time from the
dashboard. Note that CORS is open, so keys used in browser code are visible to anyone who
opens dev tools; prefer calling the API from your backend for anything sensitive.
Rate limits
Each key may make 100 requests per second. Beyond that the API answers
429 rate_limited with a Retry-After: 10 header — wait that many
seconds before retrying. The official client libraries surface this as a typed
RateLimitError and do not retry automatically.
HTTP/2 429
Retry-After: 10
Content-Type: application/json
{ "error": { "code": "rate_limited", "message": "Rate limit exceeded, retry after 10 seconds." } } Endpoints
GET /search?q=…
One search box for everything. q accepts:
- an MCC (
230) or full PLMN (23002), - a country name or ISO code (
Czech,CZ,CZE), - an operator or brand name (
O2,vodafone), - a phone number (
+420601123456; common national formats are auto-detected).
| Param | Required | Description |
|---|---|---|
q | yes | Search query (see above). |
fields | no | Comma-separated subset of Row fields. Default: all. Unknown field → 400 bad_request. |
format | no | json (default) or text. See Formats. |
limit | no | Default 50, max 500. |
offset | no | Default 0. |
Phone-number example — note the leading + must be URL-encoded as
%2B:
curl -H "X-API-Key: mcc_your_key" \
"https://mcc-mnc.dev/api/v1/search?q=%2B420601123456&fields=plmn,mcc,mnc,brand,operator&limit=3" {
"query": "+420601123456",
"phone": {
"valid": true,
"possible": true,
"type": "MOBILE",
"country": "CZ",
"calling_code": "420",
"e164": "+420601123456",
"international": "+420 601 123 456",
"national": "601 123 456"
},
"count": 12,
"results": [
{
"plmn": "23001",
"mcc": "230",
"mnc": "01",
"brand": "T-Mobile",
"operator": "T-Mobile Czech Republic"
},
{
"plmn": "23002",
"mcc": "230",
"mnc": "02",
"brand": "O2",
"operator": "O2 Czech Republic"
},
{
"plmn": "23003",
"mcc": "230",
"mnc": "03",
"brand": "Vodafone",
"operator": "Vodafone Czech Republic"
}
]
} phone is null for non-phone queries. For phone queries,
results are the operators of the matched country(ies); a valid number whose
country can't be determined still returns the phone analysis with
count: 0. count is always the total number of matches
before limit/offset pagination.
Plain text query:
curl -H "X-API-Key: mcc_your_key" \
"https://mcc-mnc.dev/api/v1/search?q=czech&fields=plmn,brand,operator,status" {
"query": "czech",
"phone": null,
"count": 12,
"results": [
{ "plmn": "23001", "brand": "T-Mobile", "operator": "T-Mobile Czech Republic", "status": "Operational" },
{ "plmn": "23002", "brand": "O2", "operator": "O2 Czech Republic", "status": "Operational" },
…
]
} GET /plmn/{plmn}
Exact lookup by concatenated code, e.g. /plmn/23002. Returns a bare
Row (see the quickstart response above), or
404 not_found if unknown. Supports fields and
format.
GET /mcc/{mcc}
All networks registered under one mobile country code. 404 if none exist.
curl -H "X-API-Key: mcc_your_key" \
"https://mcc-mnc.dev/api/v1/mcc/230?fields=plmn,mnc,brand,status" {
"mcc": "230",
"count": 12,
"results": [
{ "plmn": "23001", "mnc": "01", "brand": "T-Mobile", "status": "Operational" },
{ "plmn": "23002", "mnc": "02", "brand": "O2", "status": "Operational" },
{ "plmn": "23003", "mnc": "03", "brand": "Vodafone", "status": "Operational" },
…
]
} GET /mcc/{mcc}/{mnc}
Single network as a bare Row, 404 if unknown. The MNC is matched as
given — zero-padding is significant (02 ≠ 2) — with a
convenience fallback: if there is no exact match, the 2- or 3-digit zero-padded variant is
tried.
curl -H "X-API-Key: mcc_your_key" \
https://mcc-mnc.dev/api/v1/mcc/230/02 GET /dataset
The full dump — no search or phone logic. format=json (default) |
csv | text; optional fields.
curl -H "X-API-Key: mcc_your_key" \
"https://mcc-mnc.dev/api/v1/dataset" {
"count": 3042,
"generated_at": "2026-08-18T14:48:57.921Z",
"license": "CC BY-SA 4.0",
"results": [ … 3,042 Row objects … ]
} curl -H "X-API-Key: mcc_your_key" -OJ \
"https://mcc-mnc.dev/api/v1/dataset?format=csv"
# → mcc-mnc.csv (Content-Disposition: attachment; filename="mcc-mnc.csv") Prefer static files? The same data is downloadable without an API key — see Dataset download.
Response fields
Every endpoint returns flat, snake_case Row objects with these
21 fields. subscribers is in millions;
market_reach is a percentage of the country's total mobile subscriptions.
Use the fields parameter to request a subset.
| Field | Type | Nullable | Description |
|---|---|---|---|
plmn | string | never | MCC + MNC concatenated, e.g. "23002". Canonical key. |
mcc | string | never | Mobile country code, 3 digits. |
mnc | string | never | Mobile network code, 2–3 digits. Zero-padding is significant ("02" ≠ "2"). |
country | string | null | yes | English country name. null for International (90x) and test networks. |
iso2 | string | null | yes | ISO 3166-1 alpha-2 code, e.g. "CZ". |
iso3 | string | null | yes | ISO 3166-1 alpha-3 code, e.g. "CZE". |
iso_numeric | string | null | yes | ISO 3166-1 numeric code as string, e.g. "203". |
dial_prefix | string | null | yes | International calling prefix, e.g. "+420". |
brand | string | null | yes | Consumer-facing brand, e.g. "O2". |
operator | string | null | yes | Legal operator name, e.g. "O2 Czech Republic". |
status | string | never | E.g. "Operational", "Not operational", "Reserved", "Testing", "Unknown". |
type | string | never | "National", "International", or "Test". |
bands | string | null | yes | Radio bands summary, e.g. "GSM 900 / GSM 1800 / LTE 800 / …". |
technology | string[] | null | yes | Detailed technology lines. Europe-enriched rows only. |
ownership | string | null | yes | Owning group, e.g. "PPF". Europe-enriched rows only. |
subscribers | number | null | yes | Subscribers in millions, e.g. 5.987. Europe-enriched rows only. |
subscribers_as_of | string | null | yes | Reporting period of the subscriber figure, e.g. "2021-Q2". |
market_reach | number | null | yes | Percentage 0–100. null outside Europe. |
market_reach_basis | string | null | yes | Denominator basis, e.g. "country_total". |
rank | number | null | yes | Operator rank within its country. Europe-enriched rows only. |
notes | string | null | yes | Free-text remarks (shutdowns, renames, former identities). |
Formats
-
json(default) — as shown throughout this page. -
text— tab-separated values: header line, then one Row per line, columns infieldsorder,technologyjoined with ";", nulls as empty strings. Content-Typetext/plain; charset=utf-8. SendingAccept: text/plainalso selects text; an explicitformatparameter wins over the header. -
csv—/datasetonly. RFC 4180, served withContent-Disposition: attachment; filename="mcc-mnc.csv".
curl -H "X-API-Key: mcc_your_key" \
"https://mcc-mnc.dev/api/v1/search?q=23002&format=text&fields=plmn,mcc,mnc,brand,country" plmn mcc mnc brand country
23002 230 02 O2 Czech Republic Errors
Errors are JSON (or a single text line when the text format was requested):
{ "error": { "code": "invalid_api_key", "message": "…" } } | HTTP | Code | When |
|---|---|---|
| 400 | bad_request | Malformed query, unknown fields value, or invalid parameter. |
| 401 | missing_api_key | No X-API-Key header (or Bearer token) was sent. |
| 401 | invalid_api_key | The key is unknown or has been revoked. |
| 404 | not_found | No network matches the requested PLMN / MCC / MCC+MNC. |
| 429 | rate_limited | Over 100 requests/second for this key. Retry-After: 10 header included. |
Client libraries
Official, dependency-light clients with the same surface in every language:
Client(apiKey, {baseUrl?, timeout?}) with methods
search(q, opts?), mcc(mcc, opts?),
lookup(mcc, mnc, opts?), plmn(plmn, opts?),
dataset(opts?), and typed errors AuthError (401),
RateLimitError (429, carries retry_after),
NotFoundError (404), ApiError (anything else). No automatic
retries.
JavaScript / TypeScript
npm i mcc-mnc-dev import { Client, RateLimitError } from 'mcc-mnc-dev';
const api = new Client('mcc_your_key');
try {
const row = await api.plmn('23002');
console.log(row.operator); // "O2 Czech Republic"
} catch (err) {
if (err instanceof RateLimitError) {
console.log(`429 — retry in ${err.retryAfter}s`);
}
} Source on GitHub.
Python
pip install mcc-mnc-dev from mcc_mnc_dev import Client, RateLimitError
api = Client("mcc_your_key")
try:
row = api.lookup("230", "02")
print(row["operator"]) # O2 Czech Republic
except RateLimitError as err:
print(f"429 — retry in {err.retry_after}s") Source on GitHub.
.NET (C#)
dotnet add package MccMnc.Client using MccMnc.Client;
var api = new Client("mcc_your_key");
try
{
var row = await api.Plmn("23002");
Console.WriteLine(row.Operator); // O2 Czech Republic
}
catch (RateLimitError err)
{
Console.WriteLine($"429 — retry in {err.RetryAfter}s");
} Source on GitHub.
PHP
composer require mcc-mnc/client use MccMnc\Client;
use MccMnc\RateLimitError;
$api = new Client('mcc_your_key');
try {
$res = $api->search('vodafone', ['limit' => 5]);
echo $res['results'][0]['operator'];
} catch (RateLimitError $err) {
echo "429 — retry in {$err->retryAfter}s";
} Source on GitHub.
Dataset download
The complete dataset is also published as static files — no API key required, updated together with the API:
- networks.csv (CSV, 440 KB)
- networks.json (JSON, 1.4 MB)
- networks.min.json (minified JSON, 1.0 MB)
- countries.json (country index, 38 KB)
- meta.json (generation metadata, 0.5 KB)
Data is licensed CC BY-SA 4.0 — see About the data for sources, methodology and caveats.
Ready to build? Keys are free, instant, and never expire unless you revoke them.
Get your free API key →