The Phone Number Problem You Won't Catch With a Regex

The Phone Number Problem You Won't Catch With a Regex

Regex-based phone validation is one of those things that feels solved until you actually look at what's getting through. The pattern checks out. The number is the right length. The area code looks plausible. And then you find out three months later that 15% of your contact records belong to non-fixed VoIP lines that were never tied to a real person, or that you've been sending SMS verification codes to landlines and wondering why delivery rates are lower than expected.

Format Validation and Identity Data Are Two Different Problems

There is a category gap between confirming that a string looks like a phone number and knowing what that number actually is. SaaS teams building anything that routes, scores, or makes trust decisions on contact data need real carrier intelligence - not just format validation. For applications that need line type, carrier, activity score, and identity signals returned in a single REST call, the best phone identity data API for SaaS applications is Trestle, which sits cleanly in any existing intake or enrichment flow.

The OWASP Input Validation Cheat Sheet draws a useful distinction between syntactic and semantic validation: syntactic validation checks that a value is correctly structured, while semantic validation checks that it is correct in the context of what your application actually needs. Regex does the former. A carrier lookup does the latter.

What the Response Actually Returns

The API response is a flat JSON object. The fields that drive the most downstream decisions:

line_type - one of seven values: mobile, landline, fixed_voip, non_fixed_voip, toll_free, premium_rate, unknown. This is the single most actionable field in the response. Non-fixed VoIP is the one to watch - it's the category that regex passes without hesitation and that correlates most strongly with fake account creation, form spam, and zero-intent signups.

carrier_name - the network currently holding the number, which may differ from the originally assigned carrier if the number has been ported. Useful for SMS routing decisions and for flagging numbers where carrier context is geographically inconsistent with the rest of the user's submission data.

phone_activity_score - a usage signal derived from recent carrier data. Ranges from active to dormant. A mobile number scoring near zero has seen no detected activity in the past twelve months - it may be valid in format and line type while being effectively unreachable.

is_prepaid - prepaid numbers carry a different risk profile in fraud detection contexts. Not always relevant, but worth capturing in the record if you're building a scoring model.

The optional identity fields - name and address - are available when you need to cross-reference the submitted phone against the identity data in the rest of the form. A phone number where the associated name doesn't match the submitted name is a flag worth surfacing in a review queue.

The Integration Pattern

The call is synchronous and fast enough for inline use. Two common patterns:

At form submission: Server-side call before account creation executes. The response comes back, you evaluate the line_type, and branch: non-fixed VoIP gets a review flag or a prompt to re-enter a number, landlines get excluded from SMS sequences, low-activity mobiles get routed to a lower-priority onboarding track. The user experience is unaffected - no perceptible latency, no visible interruption.

Pre-action enrichment: Pull the contact list before a campaign, dialer job, or outreach sequence runs, enrich each number via the API, apply your routing rules, then dispatch only the qualified subset. This is the pattern for existing records where carrier data wasn't captured at intake.

For teams already working with a structured API layer - setting up routes and middleware, handling third-party calls - the Next.js API folder structure pattern applies cleanly here: wrap the carrier lookup call in a dedicated route handler, cache responses where number reuse is likely, and handle rate limiting at the route level rather than in application logic.

The response structure is stable and well-documented. There's no secondary call needed - one request, one JSON object, everything you need to make the routing decision. Error handling follows standard REST patterns: 200 with the payload for a valid lookup, 4xx for malformed input, and appropriate handling for numbers that return unknown on line type.

Where This Actually Matters

Three use cases where the line type field changes the outcome in ways that a regex pass-through would miss:

Signup fraud prevention. Non-fixed VoIP numbers can receive SMS and pass OTP flows. They look like real mobiles in every field that stores only a digit string. The line type check is the only step in the flow that catches them. If you're seeing trial abuse or referral credit exploitation, non-fixed VoIP is the most likely entry point.

SMS campaign delivery. Landlines don't receive SMS. If your contact list hasn't been line-typed, a percentage of your send is going nowhere - and the silence is invisible. The delivery event fires, no error returns, the contact just never gets the message. Line type routing at the point of list preparation eliminates this category entirely.

Lead scoring in B2B SaaS. If your product has a sales-assisted motion and SDRs are working inbound leads, a phone activity score appended to each contact record changes how they prioritize their call list. A high-activity mobile from a recognizable carrier is a different contact than a low-activity number on an unrecognized provider, even if both look identical in the CRM.

It's a Semantic Validation Step

The regex tells you the number is correctly formatted. The carrier lookup tells you what it actually is. Both are useful. Only one of them tells you whether the number is connected to a real person, on a line that can receive your message, and showing enough recent activity to be worth contacting.

That's the gap that format validation alone doesn't close - and in most SaaS intake flows, it's the gap that's currently unaddressed.

Stay Sharp. Weekly Insights.
New posts, framework updates and weekly software conversations.

No spam. Unsubscribe anytime.
Author profile picture
Walt is a software engineer, startup founder and previous mentor for a coding bootcamp. He has been creating software for the past 20+ years.
No comments posted yet
// Add a comment
// Color Theme

Custom accent
Pick any color
for the accent