The AI-first phone number validation, parsing, and intelligence library for JavaScript & TypeScript. Faster, smarter, and more powerful than traditional solutions like
libphonenumber-js.
Most libraries only parse phone numbers.
Phonex goes further:
- β Validate phone numbers (lenient, strict, AI modes)
- β Format international & national numbers
- β Detect country, carrier, and number type
- β Identify spam, fake, and reserved test numbers
- β Optimize SMS / WhatsApp / OTP delivery
- β Power AI agents with structured phone intelligence
- β Zero runtime dependencies, works in Node.js, browsers, and edge runtimes (Cloudflare Workers, Vercel Edge, Deno)
npm install @munesoft/phonexyarn add @munesoft/phonexpnpm add @munesoft/phoneximport phonex from "@munesoft/phonex";
const phone = phonex("+254712345678");
console.log(phone.valid); // true
console.log(phone.country); // "KE"
console.log(phone.countryCallingCode); // "254"
console.log(phone.national); // "712345678"
console.log(phone.international); // "+254 712 345678"
console.log(phone.e164); // "+254712345678"
console.log(phone.type); // "mobile"
console.log(phone.carrier); // "Safaricom"
console.log(phone.timezone); // "Africa/Nairobi"
console.log(phone.risk); // { score: 0, level: "low", flags: [] }CommonJS works too:
const phonex = require("@munesoft/phonex");
phonex("+254712345678");Three validation levels for different stages of your funnel:
import { validate } from "@munesoft/phonex/validate";
// Lenient: fast length-based check, ITU-T E.164 compliant.
// Use during signup so you don't reject borderline-valid international numbers.
validate("+254712345678", { level: "lenient" });
// Strict: full per-country regex validation.
// Use for KYC, billing, OTP delivery.
validate("+254712345678", { level: "strict" });
// AI: strict + anomaly detection (sequential digits, low-entropy, test ranges).
// Returns confidence score + list of anomalies. Use for fraud detection.
validate("+254712345678", { level: "ai" });
// β { valid, possible, confidence: 0.95, anomalies: [], ... }phonex.detect("+447911123456"); // "GB"
phonex.detect("0712345678", { country: "KE" }); // "KE"Turn any messy input into clean E.164:
phonex.normalize("07 12-345-678", { country: "KE" });
// "+254712345678"
phonex.normalize("+254 712.345.678");
// "+254712345678"const phone = phonex("+254712345678");
phone.formatInternational(); // "+254 712 345678"
phone.formatNational(); // "712345678"
phone.e164; // "+254712345678"phonex("+254712345678", { ai: true });Returns LLM-friendly structured data with confidence and reasoning:
{
"valid": true,
"country": "KE",
"type": "mobile",
"carrier": "Safaricom",
"ai": {
"confidence": 0.95,
"reasoning": "identified as KE; type: mobile; carrier: Safaricom; validated against curated metadata for KE",
"anomalies": []
}
}Heuristic detection of fake numbers, test ranges, and patterns commonly seen in fraud:
import { risk } from "@munesoft/phonex/risk";
risk("+254000000000");
// { score: 0.9, level: "high", flags: ["all-identical-digits"] }
risk("+12125550100");
// { score: 0.95, level: "high", flags: ["reserved-test-range"] }
risk("+254712345678");
// { score: 0, level: "low", flags: [] }Detected signals:
- Repeated digits (
0000000000) - Sequential digits (
1234567890,9876543210) - Reserved test ranges (NANPA
555-01xx, country-specific test prefixes) - Low entropy (only 1β3 unique digits)
- Implausible length
- Failed strict validation
Curated, accurate carrier mapping for supported regions. Returns null rather than guess for unsupported countries:
phonex.carrier("+254712345678"); // "Safaricom"
phonex.carrier("+254733456789"); // "Airtel Kenya"
phonex.carrier("+2348031234567"); // "MTN Nigeria"
phonex.carrier("+447911123456"); // null (UK carrier prefixes are not stable)Supported carrier-detection countries: KE, UG, NG, ZA, IN.
import { geo } from "@munesoft/phonex";
geo("+254712345678");
// { country: "KE", callingCode: "254", timezone: "Africa/Nairobi", multiTimezone: false }
geo("+14155552671");
// { country: "US", callingCode: "1", timezone: null, multiTimezone: true }Decide whether SMS, WhatsApp, or voice is appropriate for a number:
phonex.channels("+254712345678");
// { sms: true, whatsapp: true, voice: true }
phonex.channels("+442012345678");
// { sms: false, whatsapp: false, voice: true } // UK landline
phonex.channels("+8613912345678");
// { sms: true, whatsapp: false, voice: true } // CN: WhatsApp blockedPass ai: true for reasoning on each channel.
Perfect for phone-input UI components:
phonex.input("0", { country: "KE" }); // "0"
phonex.input("0712", { country: "KE" }); // "0712"
phonex.input("0712345678", { country: "KE" }); // "0712 345 678"
phonex.input("4155552671", { country: "US" }); // "415 555 2671"
phonex.input("+254712345678"); // "+254 712 345 678"When a number is malformed, suggest plausible fixes:
phonex.suggest("712345678");
// {
// input: "712345678",
// suggestions: [
// { e164: "+254712345678", country: "KE", confidence: 0.65, reason: "valid as KE national number" },
// ...
// ]
// }Process thousands of numbers with bounded concurrency:
const results = await phonex.batch(numbers, {
concurrency: 50,
country: "KE",
level: "strict",
continueOnError: true,
});Or stream them lazily:
for await (const phone of phonex.stream(numbers)) {
console.log(phone.country, phone.valid);
}stream() accepts both Iterable and AsyncIterable β works seamlessly with file streams, fetch responses, generators, and database cursors.
Aggregate stats over a list of numbers β perfect for CRM data cleaning, KYC reports, or dashboards:
phonex.analytics(numbers);
// {
// total: 5000,
// valid: 4823,
// invalid: 177,
// countryDistribution: { KE: 3200, NG: 1100, US: 523 },
// typeDistribution: { mobile: 4500, landline: 323, voip: 0, tollfree: 0, unknown: 177 },
// riskDistribution: { low: 4823, medium: 0, high: 177 },
// topCarriers: [{ carrier: "Safaricom", count: 2400 }, ...]
// }Auto-validate and normalize phone fields in every request:
import express from "express";
import phonex from "@munesoft/phonex";
const app = express();
app.use(express.json());
app.use(phonex.middleware({
fields: ["phone", "mobileNumber"], // fields to scan in body/query/params
country: "KE", // default country
level: "strict",
reject: true, // 400 on invalid; default false
normalize: true, // rewrite valid fields to E.164
}));
app.post("/signup", (req, res) => {
// req.body.phone is now "+254712345678" (normalized)
// req._phonex.phone holds the full PhonexResult
res.json({ ok: true, phone: req.body.phone });
});Works with any framework using the standard (req, res, next) signature: Express, Connect, Restify, Polka.
Mask or hash numbers for logging and storage:
phonex("+254712345678", { privacy: true });
// e164: "+********5678"
phonex("+254712345678", { privacy: "hash" });
// e164: "phx_a1b2c3d4" // deterministic hashNote:
privacy: "hash"uses FNV-1a β fast and great for deduplication keys, but not cryptographic. For GDPR / regulatory hashing, use Web CryptoSubtleCrypto.digestin your application layer.
for await (const phone of phonex.stream(asyncIterable)) {
// process one at a time
}Extend Phonex with custom logic β third-party data, alternate validation rules, audit logging:
phonex.use({
name: "twilio-lookup-enrichment",
onResult(result) {
// mutate or replace the result
return result;
},
});Phonex ships with subpath exports so you only pay for what you use:
import { validate } from "@munesoft/phonex/validate";
import { risk } from "@munesoft/phonex/risk";
import { input, suggest, normalize } from "@munesoft/phonex/input";
import { analytics } from "@munesoft/phonex/analytics";
import { middleware } from "@munesoft/phonex/middleware";
import { phonex, parse } from "@munesoft/phonex/core";Modern bundlers (Vite, esbuild, Rollup, Webpack 5, Parcel 2) will tree-shake unused features automatically. The full bundle is ~40 KB minified before tree-shaking; a typical app importing only validate is well under 20 KB.
Phonex runs everywhere modern JS runs:
| Runtime | Supported |
|---|---|
| Node.js β₯ 16 | β |
| Modern browsers (ES2020) | β |
| Cloudflare Workers | β |
| Vercel Edge Runtime | β |
| Deno | β |
| Bun | β |
No Buffer, no fs, no crypto.randomBytes β Phonex is pure JavaScript with zero runtime dependencies.
- β‘ < 1ms typical parse time (cached: ~0.01ms)
- πͺΆ Zero dependencies
- π Built-in LRU+TTL cache (2000 entries / 10-minute TTL by default)
- π³ Fully tree-shakable via subpath exports
- π¦ ~40 KB full bundle, much less when tree-shaken
Disable the cache for individual calls when needed:
phonex("+254712345678", { noCache: true });
phonex.clearCache(); // wipe the entire cachePhonex includes:
- Full ITU-T E.164 calling code table (200+ countries) β every country can be detected from its calling code.
- Curated strict-validation metadata for 30+ high-traffic countries: KE, US, GB, DE, FR, NG, ZA, IN, BR, CA, AU, JP, CN, MX, ES, IT, NL, RU, SA, AE, EG, GH, UG, TZ, RW, ET, SG, ID, PH, KR, TR.
- For countries outside the curated set, strict mode falls back to length-only validation and flags
metadataAvailable: falsein the response β so you always know the confidence level.
This is intentional: rather than ship 250 hand-rolled regexes that may be inaccurate, we ship a smaller curated set we've verified, plus a clear honest API for the long tail.
- Signup & authentication β validate at the form, normalize for storage
- Fintech & KYC β strict-mode validation before money moves
- CRM data cleaning β analytics over messy historical records
- Messaging platforms β pick the right channel (SMS / WhatsApp / voice)
- AI agents & LLM tools β structured phone intelligence with confidence scores
- Fraud detection β flag fake numbers before you spend money on lookup APIs
Full type definitions ship with the package. All public APIs are strictly typed:
import type {
PhonexResult,
PhonexOptions,
ValidationLevel,
RiskAssessment,
PhoneType,
AnalyticsResult,
} from "@munesoft/phonex";| Feature | @munesoft/phonex |
libphonenumber-js |
|---|---|---|
| Parsing | β | β |
| Formatting | β | β |
| Strict validation | β | β |
| AI / anomaly mode | β | β |
| Risk / spam detection | β | β |
| Carrier detection | β (curated) | β |
| Channel detection (SMS/WhatsApp/voice) | β | β |
| Built-in LRU cache | β | β |
| Bulk + streaming | β | β |
| Suggestions for malformed input | β | β |
| Privacy mode (mask / hash) | β | β |
| Express middleware | β | β |
| Plugin system | β | β |
| Country coverage (parsing) | 200+ | 240+ |
| Country coverage (strict validation) | 30 (curated) | 240 (autogenerated) |
| Bundle size (minified) | ~40 KB | ~145 KB |
| Zero dependencies | β | β |
Phonex is not a replacement for libphonenumber-js if you need exhaustive coverage of every country's regulatory metadata. It's the AI-first intelligence layer built for modern apps that care about developer ergonomics, AI compatibility, and feature density over raw country-count metrics.
- Real-time CDN-backed metadata updates
- ML-powered fraud detection plugin
- Expanded carrier database
- Plugin ecosystem (Twilio Lookup, Numverify, Truecaller adapters)
- React hook (
usePhonex) - CLI (
npx phonex check +254...)
phone number validation javascript Β· format phone number nodejs Β· international phone parser Β· libphonenumber alternative Β· validate phone number api Β· phone number ai validation Β· detect country from phone number Β· spam phone number detection Β· phone number carrier lookup Β· e164 formatter Β· whatsapp number validator Β· OTP delivery validation Β· KYC phone validation Β· CRM phone normalization
MIT Β© munesoft
Phonex is not just a phone number library. It's the communication intelligence layer for modern apps and AI systems.
