Why VOIP Numbers Are a Fraud Vector
SMS-based phone verification was supposed to solve the fake account problem. The logic is simple: a real phone number is tied to a real identity, a physical SIM card, a credit check, a billing address. Requiring a phone number to sign up should filter out bots and throwaway accounts.
That assumption broke years ago. Today, anyone can create a VOIP (Voice over IP) phone number in under 30 seconds, for free, with no identity verification whatsoever. Services like Google Voice, TextNow, TextFree, Talkatone, and dozens of others hand out US phone numbers that can receive SMS messages, complete with area codes that look indistinguishable from real carrier numbers.
The numbers tell the story:
- 73% of fake signups in SaaS applications use VOIP numbers, according to a 2025 Arkose Labs report.
- A single attacker can generate 50-100 VOIP numbers per hour using free services.
- Google Voice alone allows up to 6 numbers per Google account, and Google accounts are free to create.
- VOIP numbers cost $0 to obtain, while a real carrier SIM costs $10-30 and requires ID in most countries.
If your signup flow accepts any phone number that can receive an SMS, you are not verifying identity. You are verifying that someone has internet access.
A mid-size SaaS company with 10,000 monthly signups typically sees 15-25% fake accounts when using SMS verification alone. At $0.0075 per SMS (Twilio pricing), that is $11-18/month in SMS costs wasted on fake numbers. But the real cost is downstream: inflated metrics, wasted support tickets, trial abuse, and Stripe card-testing fraud that can run into thousands per month.
How Carrier Lookup Works
Every phone number in the North American Numbering Plan (NANP) is assigned to a carrier through the Number Portability Administration Center (NPAC). When a number is provisioned, whether by AT&T, Verizon, Google Voice, or TextNow, that assignment is recorded in databases maintained by the Local Exchange Routing Guide (LERG) and the Operating Company Number (OCN) registry.
Carrier lookup APIs query these databases in real-time. When you submit a phone number, the API returns:
- Line type: mobile, landline, fixed VOIP, non-fixed VOIP, toll-free, or unknown
- Carrier name: The operating company (e.g., "T-Mobile USA", "Bandwidth.com", "Google (Grand Central)")
- Is ported: Whether the number has been moved from its original carrier
- Country code: The origin country of the number
The critical distinction is between fixed VOIP and non-fixed VOIP. Fixed VOIP numbers are tied to a physical address (like a business landline running over IP). Non-fixed VOIP numbers have no address association and can be created from anywhere. Google Voice, TextNow, and the other fraud vectors are all non-fixed VOIP.
The NPAC Lookup Chain
When Auth1's API receives a phone number for verification, the lookup happens in this order:
- Number format validation — Verify E.164 format, valid country code, valid area code
- NPAC/LERG query — Determine the original carrier assignment and current carrier (if ported)
- Carrier classification — Map the carrier OCN to our internal database of 2,400+ carriers with line-type classifications
- Risk scoring — Combine carrier type, port history, area code reputation, and velocity signals into a 0-100 risk score
The entire lookup completes in under 50ms. There is no user-facing latency.
Types of VOIP Numbers and Their Risk Profiles
Not all VOIP is created equal. The risk varies dramatically by provider and use case. Here is how we classify them:
| Provider | Type | Cost | ID Required | Risk Level |
|---|---|---|---|---|
| Google Voice | Non-fixed VOIP | Free | Google account only | High |
| TextNow | Non-fixed VOIP | Free | None | Critical |
| TextFree (Pinger) | Non-fixed VOIP | Free | None | Critical |
| Talkatone | Non-fixed VOIP | Free | None | Critical |
| Bandwidth.com | Non-fixed VOIP | Paid (resold) | Varies by reseller | Medium |
| Twilio | Non-fixed VOIP | $1.15/mo | Account + payment | Medium |
| Vonage Business | Fixed VOIP | $19.99+/mo | Business verification | Low |
| AT&T / Verizon / T-Mobile | Mobile | $25+/mo + device | SSN / ID | Low |
Bandwidth.com is worth special attention. It is the underlying carrier for dozens of VOIP services, including TextNow, RingCentral, and many others. When you see "Bandwidth" as the carrier name, the number is almost certainly VOIP, but the specific risk depends on which Bandwidth reseller provisioned it. Auth1 maintains a sub-carrier mapping that identifies the actual service behind Bandwidth-provisioned numbers.
Implementation with Auth1's API
Auth1's phone verification endpoint performs carrier lookup automatically. When you send a verification request, the response includes VOIP detection data alongside the OTP delivery status. You do not need a separate API call.
The response includes three key fields:
isVoip— Boolean.trueif the number is classified as non-fixed VOIP.riskScore— Integer 0-100. Composite score factoring carrier type, port history, velocity, and area code reputation.carrierInfo— Object containing carrier name, line type, and whether the number has been ported.
Node.js Implementation
const AUTH1_API_KEY = process.env.AUTH1_API_KEY; const AUTH1_BASE = 'https://auth-api.z101.ai/api'; async function verifyPhoneNumber(phoneNumber) { const response = await fetch(`${AUTH1_BASE}/auth/sms/request`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': AUTH1_API_KEY, }, body: JSON.stringify({ phone: phoneNumber, // Optional: set your risk tolerance voipPolicy: 'block', // 'block' | 'flag' | 'allow' }), }); const data = await response.json(); // Response shape: // { // success: true, // isVoip: false, // riskScore: 12, // carrierInfo: { // name: "T-Mobile USA", // lineType: "mobile", // isPorted: false // }, // otpSent: true // } if (data.isVoip) { // VOIP number detected console.log(`Blocked VOIP number: ${data.carrierInfo.name}`); return { allowed: false, reason: 'VOIP numbers are not accepted', carrier: data.carrierInfo.name, }; } if (data.riskScore > 70) { // High risk even if not flagged as VOIP console.log(`High risk number: score ${data.riskScore}`); return { allowed: false, reason: 'Phone number flagged as high risk', riskScore: data.riskScore, }; } // OTP was sent, verification in progress return { allowed: true, otpSent: data.otpSent }; } // Usage in an Express route app.post('/api/signup', async (req, res) => { const { phone, email, name } = req.body; const phoneCheck = await verifyPhoneNumber(phone); if (!phoneCheck.allowed) { return res.status(400).json({ error: 'phone_rejected', message: phoneCheck.reason, }); } // Phone is legitimate, proceed with signup // OTP has already been sent by Auth1 res.json({ success: true, message: 'Verification code sent' }); });
Python Implementation
import os import requests AUTH1_API_KEY = os.environ["AUTH1_API_KEY"] AUTH1_BASE = "https://auth-api.z101.ai/api" def verify_phone_number(phone_number: str) -> dict: """Verify a phone number and check for VOIP.""" response = requests.post( f"{AUTH1_BASE}/auth/sms/request", headers={ "Content-Type": "application/json", "x-api-key": AUTH1_API_KEY, }, json={ "phone": phone_number, "voipPolicy": "block", }, ) data = response.json() if data.get("isVoip"): return { "allowed": False, "reason": f"VOIP detected: {data['carrierInfo']['name']}", "risk_score": data["riskScore"], } if data.get("riskScore", 0) > 70: return { "allowed": False, "reason": "High risk phone number", "risk_score": data["riskScore"], } return {"allowed": True, "otp_sent": data.get("otpSent")} # Flask example from flask import Flask, request, jsonify app = Flask(__name__) @app.route("/api/signup", methods=["POST"]) def signup(): body = request.get_json() result = verify_phone_number(body["phone"]) if not result["allowed"]: return jsonify({ "error": "phone_rejected", "message": result["reason"], }), 400 return jsonify({"success": True})
Understanding the Risk Score
The binary isVoip flag is useful, but it is not the whole picture. Auth1's risk score combines multiple signals into a single 0-100 integer that gives you granular control over your signup policy.
Risk Score Components
| Signal | Weight | Description |
|---|---|---|
| Carrier type | 40% | Non-fixed VOIP = +40, Fixed VOIP = +15, Mobile = +0, Landline = +5 |
| Port history | 15% | Recently ported numbers score higher (porting is a common fraud prep step) |
| Area code reputation | 15% | Certain area codes (e.g., 305, 347, 646) have higher VOIP density |
| Velocity | 20% | Multiple signups from the same number range in a short window |
| Known fraud carrier | 10% | Numbers from carriers with >80% fraud association (TextFree, Talkatone) |
Recommended Thresholds
- 0-25: Low risk. Allow signup, send OTP normally.
- 26-50: Medium risk. Allow signup but flag for review. Consider requiring email verification as a second factor.
- 51-70: High risk. Block signup or require additional verification (government ID, video call).
- 71-100: Critical risk. Block signup. This is almost certainly fraud.
Set your voipPolicy to "flag" instead of "block" during your first week of integration. This will send the OTP regardless but include the VOIP data in the response. Use this to analyze your traffic before enforcing a policy. Most teams find that 15-25% of their signups are VOIP when they first turn on detection.
Comparison of VOIP Detection Approaches
There are several ways to detect VOIP numbers. Here is how they compare:
| Approach | Accuracy | Latency | Cost | Catches Bandwidth |
|---|---|---|---|---|
| Twilio Lookup API | 85-90% | 200-400ms | $0.005/lookup | Partial |
| Numverify / Abstract API | 70-80% | 300-600ms | $0.001-0.01/lookup | No |
| IPQualityScore Phone API | 88-93% | 150-300ms | $0.002-0.005/lookup | Yes |
| Auth1 (built-in) | 94-97% | <50ms | Included in plan | Yes (sub-carrier mapping) |
| Manual carrier regex | 40-60% | <1ms | Free | No |
The key differentiator is sub-carrier mapping. Most lookup APIs tell you a number belongs to "Bandwidth.com" but cannot tell you whether it was provisioned by TextNow (high fraud) or RingCentral (business VOIP, lower fraud). Auth1 maintains a mapping of 200+ Bandwidth resellers and their fraud profiles, which is why the accuracy is higher.
Real-World Results
After deploying VOIP detection, Auth1 customers typically see the following changes within the first 30 days:
- 67% reduction in fake account creation
- 43% reduction in free trial abuse
- 89% reduction in card-testing attacks originating from new accounts
- $0 increase in SMS costs (detection happens before OTP is sent when using
"block"policy)
A B2B SaaS company with 8,000 monthly signups was losing approximately $6,200/month to trial abuse and card-testing fraud originating from fake accounts. After enabling Auth1's VOIP detection with a riskScore threshold of 50, fake signups dropped from 1,840/month to 220/month. Trial abuse costs dropped to near zero. The entire integration took 45 minutes.
Edge Cases to Handle
VOIP detection is not perfect. There are legitimate users who use VOIP numbers:
- International users with US-based VOIP numbers for convenience
- Privacy-conscious users who use Google Voice as their primary number
- Business users on VOIP phone systems (RingCentral, Dialpad, 8x8)
For B2C products, blocking all VOIP is usually the right call. For B2B products, consider using the risk score instead of the binary flag, and set a higher threshold (60-70) to allow business VOIP while still catching the obvious fraud vectors.
Getting Started
VOIP detection is included in all Auth1 plans, including the free tier. To enable it:
- Sign up at auth1.ai/signup and get your API key
- Add the
voipPolicyparameter to your verification requests - Handle the
isVoipandriskScorefields in the response - Monitor your fraud dashboard to tune your thresholds
The entire integration takes less than an hour. If you are currently using Twilio or another SMS provider directly, you can replace the verification call with Auth1's endpoint and get VOIP detection for free.