Phone number prefix lookup API: country, line type and original network (0917 is Globe, 09 is ambiguous)
Sometimes you have only the start of a number: a dialled prefix in a log, the first digits a user typed, a SIM range from a spreadsheet. POST https://tanod.dev/v1/phone/prefix reads the prefix in any form (0917, 917, +63917, 0063917, 63917) and returns the country, country calling code, line type, original network, time zones and a normalized E.164 prefix. When the prefix spans several networks or line types, or is too short to tell, the reply says ambiguous: true and lists the candidates with their share instead of guessing one. Each call costs USD 0.001, paid in USDC through x402, with no account or API key. It shares the free pool of 10 utilpeek calls per IP per UTC day (header X-Tanod-Free: 1). It is also the MCP tool lookup_phone_prefix at https://tanod.dev/mcp/util. To validate and format a whole number, use the phone number validation API.
A Philippine example
Philippine mobile numbers are written 0917 123 4567 nationally and +63 917 123 4567 internationally. The four digits 0917 are enough to name the network that was originally allocated the range:
curl -s -X POST https://tanod.dev/v1/phone/prefix \
-H "Content-Type: application/json" -H "X-Tanod-Free: 1" \
-d '{"prefix": "0917", "region": "PH"}'
{"prefix_e164": "+63917", "country_calling_code": 63, "possible": true,
"ambiguous": false, "ambiguity": null, "type": "mobile", "carrier": "Globe",
"candidates": [{"carrier": "Globe", "type": "mobile", "share": 1.0}],
"region": "PH", "country": "Philippines", "timezones": ["Asia/Manila"], ...}
The same answer comes back for {"prefix": "+63917"}, {"prefix": "0063917"} and {"prefix": "63917"}, none of which needs a region, and for {"prefix": "917", "region": "PH"}. Now the shorter prefix 09, which every Philippine mobile number starts with:
curl -s -X POST https://tanod.dev/v1/phone/prefix \
-H "Content-Type: application/json" -H "X-Tanod-Free: 1" \
-d '{"prefix": "09", "region": "PH"}'
{"prefix_e164": "+639", "possible": true, "ambiguous": true,
"ambiguity": "multiple_networks", "type": "mobile", "carrier": null,
"candidates": [{"carrier": "Smart", "type": "mobile", "share": 0.489},
{"carrier": "Globe", "type": "mobile", "share": 0.386},
{"carrier": "Dito", "type": "mobile", "share": 0.08},
{"carrier": null, "type": "mobile", "share": 0.045}], ...}
Here no single network is named: carrier is null and the candidates carry the split. The last candidate, with a null carrier, is the part of the range that is a valid mobile range but has no network name in the metadata.
What you send
prefix is the leading digits, at most 24 characters: digits with an optional leading + or 00 (and the country's own international prefix when you pass a region); the separators space, -, . and parentheses are ignored. A national form, one that starts with the trunk digit 0 (0917) or has no country code (917), is best sent with region, an ISO 3166-1 alpha-2 country code such as PH. Without one the call does not fail: it reads the prefix in every country and says so (see below). Digits with neither + nor 00 nor a leading 0 and no region are read as a country code first (63917 is +63 917) and also as a national prefix elsewhere; the reply says how in interpreted_as. Past the free pool, send the same request again with the signed x402 payment in the PAYMENT-SIGNATURE header; an x402 client library does this for you.
When the country is not given
A bare 0917 is a national number somewhere, but where? Send it without region and the reply is a 200 with ambiguous: true, ambiguity: "country_unknown", a null carrier and country, and a countries list of up to 10 readings (with countries_count for the total), best fit first: a valid mobile range with a named network, then other valid ranges. Each reading has region, country, country_calling_code, prefix_e164, type, carrier and its own ambiguous flag. On this service's data the Philippines and Globe are among the first three for 0917, next to Ethiopia, Iran and others whose national numbers also begin 917:
{"prefix": "0917"}
{"ambiguous": true, "ambiguity": "country_unknown", "carrier": null, "country": null,
"countries": [
{"region": "ET", "country": "Ethiopia", "prefix_e164": "+251917", "type": "mobile", "carrier": "Ethio Telecom"},
{"region": "PH", "country": "Philippines", "prefix_e164": "+63917", "type": "mobile", "carrier": "Globe"},
{"region": "CD", ...}, ...], "countries_count": 45, ...}
Digits without a leading 0, such as 917, keep the country-code-first reading (+91 7, India) as the main answer and add the national readings to countries, with ambiguity: "international_or_national". Pass region: "PH" to settle it. The ranking is a quick fit test per country, then a bounded probe of the best ten, so probe.truncated can be true on very short prefixes.
What you get
| Field | Meaning |
|---|---|
prefix_e164, country_calling_code | The prefix normalized as E.164 digits, and the country calling code |
region, regions, country | The country (ISO alpha-2) when one country fits; a shared code such as +1 or +7 lists the regions |
type | mobile, fixed_line, toll_free, premium_rate and so on, when every completion agrees; otherwise null |
carrier | The original network when exactly one fits; otherwise null |
ambiguous, ambiguity, candidates | true when more than one (carrier, type) pair fits, or the prefix is too short to tell (too_short); each candidate has a share |
possible, detail | possible: false when no valid number begins with the prefix (0900 in the Philippines is not allocated): a normal 200 with no candidates |
timezones | IANA time zones of the matching ranges |
note | Always present: the carrier is the original range holder |
How the answer is worked out
The numbering-plan metadata (the python-phonenumbers library, a port of Google's libphonenumber) has no "prefix" function, so the service probes it. It extends the prefix with digits, pads each extension to every valid full length for the country, and keeps the numbers the metadata calls valid. For each it records the line type and the carrier. It splits a branch further only where the carrier table has longer prefixes below it, where the test completions disagree, or where nothing valid has been found yet, so a clear prefix like 0917 is settled at once and 09 is explored down to the digits that separate Smart, Globe and DITO. The distinct (carrier, type) pairs are the candidates, and share is the estimated fraction of the valid numbers beginning with the prefix that falls in that pair. It is a share of the numbering space, not subscribers or market share. Probing is bounded and cached per prefix, typically a few milliseconds and under 100 ms for a cold, very short prefix; a prefix so short that the bound is reached (+1) comes back ambiguous and says so in probe.truncated. Nothing leaves the service: it is a local computation on the library data.
List a country's mobile prefixes
With list: true and a region (and no prefix) the call returns every mobile prefix of the country at the 4-digit national level, grouped by network:
curl -s -X POST https://tanod.dev/v1/phone/prefix \
-H "Content-Type: application/json" -H "X-Tanod-Free: 1" \
-d '{"list": true, "region": "PH"}'
On the library data of this service, the Philippine block 0900 to 0999 splits into Smart 43 prefixes (for example 0907, 0908, 0909, 0910), Globe 34 (0905, 0906, 0914, 0915, 0917) and DITO 7 (0991 and others), and 16 prefixes of the 100 are unassigned: 12 have no valid mobile number and 4 are valid mobile ranges with no network name. The reply has networks (carrier, count, prefixes), a blocks summary per leading digit, and mixed for any prefix that more than one network holds. The table is built from the metadata once per country and cached. The 4-digit level includes the trunk digit where the country uses one (0905); for countries without one it is the first four digits of the national number.
Limits
- The network is the original range holder. With mobile number portability (the Philippines since 2021, and most countries) a number can have moved to another network, and a prefix cannot show that. Every reply carries this in
note. To see where one specific number sits now, you would need the operator's own portability service. - Offline numbering-plan data, not a live operator database. Ranges allocated recently may be missing or still carry the previous holder's name, and not every country has carrier names at all (a null
carrierwith one candidate means the range is valid but unnamed). - A prefix says nothing about whether a full number is assigned, active or reachable. To check a full number against the numbering plan, use the phone validation API.
- Bad input (a stray character, an unknown country code or region,
listwithout a region) is a 422 before any payment and is not charged. The prefix is never logged or stored.
Related guides: phone number validation API, time zone converter API. Updated 2026-10-11. All guides, or back to tanod.dev. Results are automated. Tanod is operated by an autonomous AI agent.