Many web forms validate U.S. phone numbers by stripping non-digits and checking /^\d{10}$/. That accepts 000-000-0000, 911-555-0100, and 212-988-1234—none of which can be assigned to a subscriber—while stricter regexes copied from Stack Overflow often reject newer overlay area codes.
Here is how the North American Numbering Plan (NANP) actually structures a 10-digit number (NPA-NXX-XXXX), along with a small JavaScript parser that checks structural rules, flags reserved ranges, and separates geographic area codes from toll-free codes.
The three parts of a 10-digit NANP number
Under NANPA's numbering plan, a 10-digit number is split into:
-
NPA(Numbering Plan Area / area code, 3 digitsNXX):- The first digit
Nmust be2–9(0and1are used for operator and trunk prefixes). - Codes ending in
11(211through911) areN11service codes, not area codes. - Codes with
9as the middle digit (N9X) are reserved for future NANP expansion. -
555,958, and959are reserved non-geographic/test NPAs.
- The first digit
-
NXX(Central Office / exchange code, 3 digits):- The first digit must also be
2–9. - Exchanges ending in
11(N11) are excluded. -
988is reserved nationwide as the Suicide & Crisis Lifeline prefix. In 2020 (FCC 20-100), the FCC ordered mandatory 10-digit dialing across 87 area codes that previously permitted 7-digit local dialing and had assigned988as a central office prefix, before988went live nationwide in July 2022.
- The first digit must also be
-
XXXX(Line number, 4 digits0000–9999):- Within the
555exchange,555-0100through555-0199are set aside for fictional/entertainment use.
- Within the
The parser
const TOLL_FREE = new Set(["800", "833", "844", "855", "866", "877", "888"]);
function parseNanpNumber(input) {
const digits = String(input).replace(/\D/g, "");
const ten = digits.length === 11 && digits.startsWith("1") ? digits.slice(1) : digits;
if (ten.length !== 10) return { valid: false, reason: "wrong_length" };
const npa = ten.slice(0, 3);
const nxx = ten.slice(3, 6);
const line = ten.slice(6);
if (npa[0] < "2" || npa[0] > "9") return { valid: false, reason: "invalid_npa_first_digit" };
if (npa.slice(1) === "11") return { valid: false, reason: "n11_service_code" };
if (npa[1] === "9") return { valid: false, reason: "reserved_expansion_code" };
if (npa === "555" || npa === "958" || npa === "959") return { valid: false, reason: "reserved_npa" };
if (nxx[0] < "2" || nxx[0] > "9") return { valid: false, reason: "invalid_nxx_first_digit" };
if (nxx.slice(1) === "11") return { valid: false, reason: "n11_central_office_code" };
if (nxx === "988") return { valid: false, reason: "reserved_988_crisis_prefix" };
if (nxx === "555" && Number(line) >= 100 && Number(line) <= 199) {
return { valid: false, reason: "fictional_555_01xx" };
}
return {
valid: true,
e164: `+1${ten}`,
npa,
nxx,
line,
kind: TOLL_FREE.has(npa) ? "toll-free" : npa === "900" ? "premium" : "geographic_or_non_geo",
};
}
Testing real vs. reserved numbers
const samples = [
"(212) 456-7890", // Valid Manhattan format
"+1-833-240-9100", // Valid toll-free
"202-555-0143", // Fictional 555-01XX range
"617-988-2000", // Reserved 988 prefix
"411-234-5678", // N11 service code in NPA position
"215-911-3000", // N11 service code in NXX position
];
for (const s of samples) {
console.log(s, "->", parseNanpNumber(s));
}
Output:
| Input | valid |
e164 |
kind / reason
|
|---|---|---|---|
(212) 456-7890 |
true |
+12124567890 |
geographic_or_non_geo |
+1-833-240-9100 |
true |
+18332409100 |
toll-free |
202-555-0143 |
false |
— | fictional_555_01xx |
617-988-2000 |
false |
— | reserved_988_crisis_prefix |
411-234-5678 |
false |
— | n11_service_code |
215-911-3000 |
false |
— | n11_central_office_code |
Why structural validity is not the same as an active area code
A number like 222-234-5678 passes every structural NXX rule above, yet 222 is not an assigned U.S. area code. NANPA's public database lists 372 geographic area codes in service across the 50 U.S. states and D.C. (plus 6 in U.S. territories and 7 active toll-free codes: 800, 833, 844, 855, 866, 877, and 888).
Even historic East Coast codes added overlays as their original pools filled up:
-
Manhattan (212 area code guide): One of the 86 original 1947 codes; shares Manhattan (except Marble Hill) with overlays
646,332, and citywide917. -
Boston (617 area code guide): Assigned in 1947; shares Boston and surrounding eastern Massachusetts communities with overlay
857. -
Philadelphia (215 area code guide): Assigned in 1947; shares Philadelphia and its suburbs with overlays
267and445. -
Washington, D.C. (202 area code guide): Assigned in 1947; stood alone for 74 years before overlay
771entered service in 2021. -
Baltimore & Eastern Maryland (410 area code guide): Split from
301in 1991 and now shares its territory with overlays443and667.
If you want to validate against the exact list of active U.S. codes instead of only structural rules, you can browse the complete state-by-state table on the all U.S. area codes by state page or search individual metro guides in the U.S. area code directory.
Disclosure: I work with the team at EaseDial, which publishes the area code directory and state dataset linked above.
Top comments (0)