Carrier Intelligence: Understanding Mobile Network Information
Leverage carrier intelligence for enhanced phone validation, fraud detection, and user experience optimization.
Table of Contents
Table of Contents
Carrier Intelligence: Understanding Mobile Network Information
Carrier intelligence provides valuable insights into mobile network characteristics, user behavior, and service capabilities. Leveraging this information enhances validation accuracy and enables sophisticated fraud detection.
Carrier Intelligence Overview
Business Impact
- User experience enhancement
- Operational efficiency gains
- Cost optimization opportunities
- Risk mitigation strategies
Carrier Intelligence Overview
Carrier intelligence systems analyze mobile network data to provide real-time insights about phone numbers, carriers, and network characteristics. This technology enables businesses to:
- Validate phone numbers with carrier-level accuracy
- Detect fraud through network behavior analysis
- Optimize user experience by understanding network capabilities
- Reduce costs by preventing invalid transactions
Key Components
HLR (Home Location Register) Lookups
- Real-time carrier identification
- Network status verification
- Roaming and portability detection
- Location-based intelligence
MCC/MNC Database
- Mobile Country Code (MCC) identification
- Mobile Network Code (MNC) mapping
- Carrier name resolution
- Network technology detection
Fraud Detection Engine
- Velocity analysis
- Pattern recognition
- Blacklist checking
- Risk scoring algorithms
HLR Lookup System for Real-Time Carrier Intelligence
// Production-ready HLR lookup system for carrier intelligence and phone validation
interface HLRRequest {
phoneNumber: string
countryCode?: string
includeLocation?: boolean
includeRoaming?: boolean
timeout?: number
}
interface HLRResponse {
phoneNumber: string
imsi?: string
mcc?: string
mnc?: string
msisdn?: string
status: 'active' | 'inactive' | 'invalid' | 'ported' | 'unknown'
carrier: {
name: string
country: string
network: string
mcc: string
mnc: string
}
location?: {
country: string
region: string
city: string
coordinates?: {
latitude: number
longitude: number
}
}
roaming?: {
isRoaming: boolean
originalCarrier?: string
currentCarrier?: string
}
ported?: {
isPorted: boolean
originalCarrier?: string
portedDate?: number
}
lastSeen?: number
firstSeen?: number
}
interface CarrierDatabaseEntry {
mcc: string
mnc: string
country: string
carrier: string
network: string
bands: string[]
technologies: string[]
roamingAgreements: string[]
lastUpdated: number
}
class HLRIntelligenceSystem {
private carrierDatabase: Map<string, CarrierDatabaseEntry> = new Map()
private cache: Map<string, { response: HLRResponse; timestamp: number }> = new Map()
private requestQueue: Array<{ request: HLRRequest; resolve: Function; reject: Function }> = []
private isProcessingQueue = false
private rateLimitDelay = 100 // ms between requests
private maxConcurrentRequests = 5
constructor() {
this.initializeCarrierDatabase()
this.startQueueProcessor()
}
async performHLRLookup(request: HLRRequest): Promise<HLRResponse> {
const cacheKey = this.generateCacheKey(request)
// Check cache first (5 minutes TTL)
const cached = this.getCachedResponse(cacheKey)
if (cached) {
return cached
}
return new Promise((resolve, reject) => {
this.requestQueue.push({ request, resolve, reject })
this.processQueue()
})
}
private generateCacheKey(request: HLRRequest): string {
return Buffer.from(`${request.phoneNumber}-${request.countryCode || ''}`).toString('base64')
}
private getCachedResponse(cacheKey: string): HLRResponse | null {
const cached = this.cache.get(cacheKey)
if (cached && Date.now() - cached.timestamp < 5 * 60 * 1000) {
return cached.response
}
if (cached) {
this.cache.delete(cacheKey)
}
return null
}
private async processQueue(): Promise<void> {
if (this.isProcessingQueue || this.requestQueue.length === 0) {
return
}
this.isProcessingQueue = true
while (this.requestQueue.length > 0) {
const batch = this.requestQueue.splice(0, this.maxConcurrentRequests)
const batchPromises = batch.map(async ({ request, resolve, reject }) => {
try {
const response = await this.executeHLRRequest(request)
this.cacheResponse(request, response)
resolve(response)
} catch (error) {
reject(error)
}
})
await Promise.allSettled(batchPromises)
// Rate limiting delay
if (this.requestQueue.length > 0) {
await new Promise(resolve => setTimeout(resolve, this.rateLimitDelay))
}
}
this.isProcessingQueue = false
}
private async executeHLRRequest(request: HLRRequest): Promise<HLRResponse> {
// In production, this would connect to HLR providers like:
// - TMT Analysis, OpenCellID, Combain, etc.
// For demo, simulate HLR response
const phoneNumber = this.normalizePhoneNumber(request.phoneNumber, request.countryCode)
if (!this.isValidPhoneNumber(phoneNumber)) {
throw new Error('Invalid phone number format')
}
// Simulate HLR lookup delay
await new Promise(resolve => setTimeout(resolve, 200 + Math.random() * 300))
return this.generateMockHLRResponse(phoneNumber, request)
}
private normalizePhoneNumber(phoneNumber: string, countryCode?: string): string {
// Remove all non-digit characters
let normalized = phoneNumber.replace(/D/g, '')
// Add country code if not present
if (countryCode && !normalized.startsWith(countryCode)) {
normalized = countryCode + normalized
}
return normalized
}
private isValidPhoneNumber(phoneNumber: string): boolean {
// Basic validation - should be 10-15 digits
return phoneNumber.length >= 10 && phoneNumber.length <= 15 && /^d+$/.test(phoneNumber)
}
private generateMockHLRResponse(phoneNumber: string, request: HLRRequest): HLRResponse {
const mockCarriers = [
{ mcc: '250', mnc: '01', country: 'RU', carrier: 'MTS', network: 'MTS Russia' },
{ mcc: '250', mnc: '02', country: 'RU', carrier: 'MegaFon', network: 'MegaFon Russia' },
{ mcc: '250', mnc: '20', country: 'RU', carrier: 'Tele2', network: 'Tele2 Russia' },
{ mcc: '250', mnc: '99', country: 'RU', carrier: 'Beeline', network: 'Beeline Russia' },
{ mcc: '310', mnc: '120', country: 'US', carrier: 'T-Mobile', network: 'T-Mobile USA' },
{ mcc: '310', mnc: '260', country: 'US', carrier: 'Verizon', network: 'Verizon Wireless' }
]
// Select carrier based on phone number prefix (simplified)
const prefix = phoneNumber.substring(0, 3)
let selectedCarrier = mockCarriers[0]
if (prefix === '791' || prefix === '792') selectedCarrier = mockCarriers[0] // MTS
else if (prefix === '793' || prefix === '798') selectedCarrier = mockCarriers[1] // MegaFon
else if (prefix === '795') selectedCarrier = mockCarriers[2] // Tele2
else if (prefix === '796' || prefix === '790') selectedCarrier = mockCarriers[3] // Beeline
else if (phoneNumber.startsWith('1')) selectedCarrier = mockCarriers[4] // T-Mobile
else selectedCarrier = mockCarriers[5] // Verizon
const isRoaming = Math.random() < 0.1 // 10% chance of roaming
const isPorted = Math.random() < 0.15 // 15% chance of ported number
const response: HLRResponse = {
phoneNumber: request.phoneNumber,
imsi: `310150${Math.random().toString().substring(2, 15)}`,
mcc: selectedCarrier.mcc,
mnc: selectedCarrier.mnc,
status: Math.random() < 0.85 ? 'active' : 'inactive', // 85% active
carrier: {
name: selectedCarrier.carrier,
country: selectedCarrier.country,
network: selectedCarrier.network,
mcc: selectedCarrier.mcc,
mnc: selectedCarrier.mnc
}
}
// Add location data if requested
if (request.includeLocation) {
response.location = {
country: selectedCarrier.country === 'RU' ? 'Russia' : 'United States',
region: selectedCarrier.country === 'RU' ? 'Moscow' : 'California',
city: selectedCarrier.country === 'RU' ? 'Moscow' : 'Los Angeles',
coordinates: selectedCarrier.country === 'RU'
? { latitude: 55.7558, longitude: 37.6176 }
: { latitude: 34.0522, longitude: -118.2437 }
}
}
// Add roaming data if requested
if (request.includeRoaming) {
response.roaming = {
isRoaming,
originalCarrier: isRoaming ? selectedCarrier.carrier : undefined,
currentCarrier: isRoaming ? 'Roaming Partner' : selectedCarrier.carrier
}
}
// Add ported information
if (isPorted) {
response.ported = {
isPorted: true,
originalCarrier: 'Original Carrier',
portedDate: Date.now() - Math.random() * 365 * 24 * 60 * 60 * 1000
}
}
// Add timestamps
response.lastSeen = Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000 // Within last week
response.firstSeen = Date.now() - Math.random() * 365 * 24 * 60 * 60 * 1000 // Within last year
return response
}
private initializeCarrierDatabase(): void {
// In production, load comprehensive carrier database
// For demo, populate with sample data
const carriers: CarrierDatabaseEntry[] = [
{
mcc: '250',
mnc: '01',
country: 'RU',
carrier: 'MTS',
network: 'MTS Russia',
bands: ['GSM 900', 'GSM 1800', 'UMTS 2100', 'LTE 1800', 'LTE 2600'],
technologies: ['2G', '3G', '4G', 'VoLTE'],
roamingAgreements: ['US', 'EU', 'CN', 'IN'],
lastUpdated: Date.now()
},
{
mcc: '310',
mnc: '120',
country: 'US',
carrier: 'T-Mobile',
network: 'T-Mobile USA',
bands: ['GSM 1900', 'UMTS 1900', 'LTE 700', 'LTE 1900'],
technologies: ['3G', '4G', '5G'],
roamingAgreements: ['CA', 'MX', 'EU'],
lastUpdated: Date.now()
}
]
carriers.forEach(carrier => {
const key = `${carrier.mcc}-${carrier.mnc}`
this.carrierDatabase.set(key, carrier)
})
console.log(`Carrier database initialized with ${carriers.length} entries`)
}
private startQueueProcessor(): void {
// Start background queue processor
setInterval(() => {
if (this.requestQueue.length > 0 && !this.isProcessingQueue) {
this.processQueue()
}
}, 100)
}
private cacheResponse(request: HLRRequest, response: HLRResponse): void {
const cacheKey = this.generateCacheKey(request)
this.cache.set(cacheKey, {
response,
timestamp: Date.now()
})
// Clean old cache entries (keep only last 10000)
if (this.cache.size > 10000) {
const entries = Array.from(this.cache.entries())
const oldestKey = entries.sort(([, a], [, b]) => a.timestamp - b.timestamp)[0][0]
this.cache.delete(oldestKey)
}
}
// Batch HLR lookups for multiple numbers
async performBatchHLRLookup(requests: HLRRequest[]): Promise<Map<string, HLRResponse>> {
const results = new Map<string, HLRResponse>()
// Process in batches of 10
const batchSize = 10
for (let i = 0; i < requests.length; i += batchSize) {
const batch = requests.slice(i, i + batchSize)
const batchPromises = batch.map(async (request) => {
try {
const response = await this.performHLRLookup(request)
return { phoneNumber: request.phoneNumber, response }
} catch (error) {
console.error(`Batch HLR lookup failed for ${request.phoneNumber}:`, error)
return { phoneNumber: request.phoneNumber, response: null }
}
})
const batchResults = await Promise.all(batchPromises)
batchResults.forEach(({ phoneNumber, response }) => {
if (response) {
results.set(phoneNumber, response)
}
})
// Small delay between batches
if (i + batchSize < requests.length) {
await new Promise(resolve => setTimeout(resolve, 500))
}
}
return results
}
// Get carrier statistics
getCarrierStatistics(): {
totalLookups: number
uniqueCarriers: number
activeSubscribers: number
roamingSubscribers: number
portedNumbers: number
topCarriers: Array<{ carrier: string; count: number }>
} {
const responses = Array.from(this.cache.values()).map(c => c.response)
const total = responses.length
if (total === 0) {
return {
totalLookups: 0,
uniqueCarriers: 0,
activeSubscribers: 0,
roamingSubscribers: 0,
portedNumbers: 0,
topCarriers: []
}
}
const carriers = responses.map(r => r.carrier.name)
const uniqueCarriers = new Set(carriers).size
const activeSubscribers = responses.filter(r => r.status === 'active').length
const roamingSubscribers = responses.filter(r => r.roaming?.isRoaming).length
const portedNumbers = responses.filter(r => r.ported?.isPorted).length
// Count carrier occurrences
const carrierCounts = new Map<string, number>()
carriers.forEach(carrier => {
const count = carrierCounts.get(carrier) || 0
carrierCounts.set(carrier, count + 1)
})
const topCarriers = Array.from(carrierCounts.entries())
.sort(([, a], [, b]) => b - a)
.slice(0, 10)
.map(([carrier, count]) => ({ carrier, count }))
return {
totalLookups: total,
uniqueCarriers,
activeSubscribers,
roamingSubscribers,
portedNumbers,
topCarriers
}
}
}
// Initialize HLR intelligence system
const hlrIntelligenceSystem = new HLRIntelligenceSystem()
// HLR lookup endpoint
app.post('/api/hlr/lookup', async (req, res) => {
try {
const { phoneNumber, countryCode, includeLocation, includeRoaming } = req.body
if (!phoneNumber) {
return res.status(400).json({ error: 'phoneNumber required' })
}
const request: HLRRequest = {
phoneNumber,
countryCode,
includeLocation,
includeRoaming,
timeout: 10000
}
const response = await hlrIntelligenceSystem.performHLRLookup(request)
res.json({
hlr: response,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('HLR lookup error:', error)
res.status(500).json({ error: 'HLR lookup failed' })
}
})
// Batch HLR lookup endpoint
app.post('/api/hlr/lookup-batch', async (req, res) => {
try {
const { phoneNumbers, countryCode, includeLocation, includeRoaming } = req.body
if (!Array.isArray(phoneNumbers)) {
return res.status(400).json({ error: 'phoneNumbers array required' })
}
const requests: HLRRequest[] = phoneNumbers.map(phoneNumber => ({
phoneNumber,
countryCode,
includeLocation,
includeRoaming,
timeout: 10000
}))
const results = await hlrIntelligenceSystem.performBatchHLRLookup(requests)
res.json({
results: Object.fromEntries(results.entries()),
count: results.size,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Batch HLR lookup error:', error)
res.status(500).json({ error: 'Batch HLR lookup failed' })
}
})
// HLR statistics endpoint
app.get('/api/hlr/statistics', (req, res) => {
try {
const stats = hlrIntelligenceSystem.getCarrierStatistics()
res.json({
statistics: stats,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('HLR statistics error:', error)
res.status(500).json({ error: 'Statistics retrieval failed' })
}
})
console.log('HLR Intelligence System initialized')Carrier Detection and Intelligence Engine
// Advanced carrier intelligence engine for phone number analysis
interface CarrierIntelligenceConfig {
enableHLRLookup: boolean
enableNetworkAnalysis: boolean
enableFraudDetection: boolean
cacheResults: boolean
cacheDuration: number
maxRetries: number
}
interface PhoneNumberAnalysis {
phoneNumber: string
normalizedNumber: string
country: {
code: string
name: string
region: string
}
carrier: {
name: string
mcc: string
mnc: string
networkType: 'gsm' | 'cdma' | 'lte' | '5g' | 'unknown'
bands: string[]
}
validation: {
isValid: boolean
format: 'e164' | 'national' | 'international' | 'invalid'
checksumValid: boolean
lengthValid: boolean
}
intelligence: {
isActive: boolean
isRoaming: boolean
isPorted: boolean
lastSeen: number
riskScore: number
confidence: number
}
network: {
technology: string[]
bands: string[]
roamingAgreements: string[]
coverage: {
area: string[]
quality: 'excellent' | 'good' | 'fair' | 'poor'
}
}
fraudIndicators: {
velocityCheck: boolean
patternAnalysis: boolean
blacklisted: boolean
suspiciousActivity: boolean
riskFactors: string[]
}
}
interface FraudDetectionResult {
phoneNumber: string
riskScore: number // 0-100
riskLevel: 'low' | 'medium' | 'high' | 'critical'
indicators: string[]
recommendations: string[]
blocked: boolean
requiresReview: boolean
}
class CarrierIntelligenceEngine {
private config: CarrierIntelligenceConfig
private hlrSystem: HLRIntelligenceSystem
private numberCache: Map<string, PhoneNumberAnalysis> = new Map()
private fraudCache: Map<string, FraudDetectionResult> = new Map()
constructor(config: CarrierIntelligenceConfig) {
this.config = config
this.hlrSystem = new HLRIntelligenceSystem()
}
async analyzePhoneNumber(phoneNumber: string, countryCode?: string): Promise<PhoneNumberAnalysis> {
const normalizedNumber = this.normalizePhoneNumber(phoneNumber, countryCode)
// Check cache first
if (this.config.cacheResults) {
const cached = this.getCachedAnalysis(normalizedNumber)
if (cached) {
return cached
}
}
try {
// Perform comprehensive phone number analysis
const [basicInfo, carrierInfo, validationInfo, intelligenceInfo] = await Promise.all([
this.getBasicNumberInfo(normalizedNumber),
this.getCarrierInformation(normalizedNumber),
this.validatePhoneNumberFormat(normalizedNumber),
this.gatherIntelligenceData(normalizedNumber)
])
const analysis: PhoneNumberAnalysis = {
phoneNumber,
normalizedNumber,
...basicInfo,
carrier: carrierInfo,
validation: validationInfo,
intelligence: intelligenceInfo.intelligence,
network: intelligenceInfo.network,
fraudIndicators: intelligenceInfo.fraudIndicators
}
// Cache result
if (this.config.cacheResults) {
this.cacheAnalysis(normalizedNumber, analysis)
}
return analysis
} catch (error) {
console.error('Phone number analysis failed:', error)
// Return basic analysis on error
return {
phoneNumber,
normalizedNumber,
country: { code: countryCode || 'US', name: 'Unknown', region: 'Unknown' },
carrier: {
name: 'Unknown',
mcc: '000',
mnc: '00',
networkType: 'unknown',
bands: []
},
validation: {
isValid: false,
format: 'invalid',
checksumValid: false,
lengthValid: false
},
intelligence: {
isActive: false,
isRoaming: false,
isPorted: false,
lastSeen: 0,
riskScore: 100,
confidence: 0
},
network: {
technology: [],
bands: [],
roamingAgreements: [],
coverage: {
area: [],
quality: 'poor'
}
},
fraudIndicators: {
velocityCheck: false,
patternAnalysis: false,
blacklisted: true,
suspiciousActivity: true,
riskFactors: ['Analysis failed']
}
}
}
}
private normalizePhoneNumber(phoneNumber: string, countryCode?: string): string {
let normalized = phoneNumber.replace(/D/g, '')
// Add country code if not present and we have it
if (countryCode && !normalized.startsWith(countryCode)) {
normalized = countryCode + normalized
}
return normalized
}
private async getBasicNumberInfo(phoneNumber: string): Promise<{
country: PhoneNumberAnalysis['country']
}> {
// In production, use comprehensive number database
// For demo, use simple country detection based on prefixes
const countryPrefixes: Record<string, { code: string; name: string; region: string }> = {
'1': { code: 'US', name: 'United States', region: 'North America' },
'7': { code: 'RU', name: 'Russia', region: 'Europe' },
'44': { code: 'GB', name: 'United Kingdom', region: 'Europe' },
'33': { code: 'FR', name: 'France', region: 'Europe' },
'49': { code: 'DE', name: 'Germany', region: 'Europe' },
'39': { code: 'IT', name: 'Italy', region: 'Europe' },
'34': { code: 'ES', name: 'Spain', region: 'Europe' },
'31': { code: 'NL', name: 'Netherlands', region: 'Europe' }
}
let countryCode = '1' // Default to US
for (let i = 1; i <= 3; i++) {
const prefix = phoneNumber.substring(0, i)
if (countryPrefixes[prefix]) {
countryCode = prefix
break
}
}
return {
country: countryPrefixes[countryCode] || countryPrefixes['1']
}
}
private async getCarrierInformation(phoneNumber: string): Promise<PhoneNumberAnalysis['carrier']> {
if (!this.config.enableHLRLookup) {
return {
name: 'Unknown',
mcc: '000',
mnc: '00',
networkType: 'unknown',
bands: []
}
}
try {
const hlrResponse = await this.hlrSystem.performHLRLookup({
phoneNumber,
includeLocation: false,
includeRoaming: false
})
return {
name: hlrResponse.carrier.name,
mcc: hlrResponse.carrier.mcc,
mnc: hlrResponse.carrier.mnc,
networkType: this.determineNetworkType(hlrResponse.carrier.mcc, hlrResponse.carrier.mnc),
bands: this.getCarrierBands(hlrResponse.carrier.mcc, hlrResponse.carrier.mnc)
}
} catch (error) {
console.error('Carrier lookup failed:', error)
return {
name: 'Unknown',
mcc: '000',
mnc: '00',
networkType: 'unknown',
bands: []
}
}
}
private validatePhoneNumberFormat(phoneNumber: string): PhoneNumberAnalysis['validation'] {
const length = phoneNumber.length
const isValidLength = length >= 10 && length <= 15
// Basic checksum validation (simplified)
const checksumValid = this.validateChecksum(phoneNumber)
return {
isValid: isValidLength && checksumValid,
format: length > 10 ? 'international' : 'national',
checksumValid,
lengthValid: isValidLength
}
}
private async gatherIntelligenceData(phoneNumber: string): Promise<{
intelligence: PhoneNumberAnalysis['intelligence']
network: PhoneNumberAnalysis['network']
fraudIndicators: PhoneNumberAnalysis['fraudIndicators']
}> {
const intelligence: PhoneNumberAnalysis['intelligence'] = {
isActive: Math.random() > 0.1, // 90% active
isRoaming: Math.random() > 0.9, // 10% roaming
isPorted: Math.random() > 0.85, // 15% ported
lastSeen: Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000, // Within last 30 days
riskScore: Math.floor(Math.random() * 100),
confidence: 75 + Math.floor(Math.random() * 25) // 75-100%
}
const network: PhoneNumberAnalysis['network'] = {
technology: ['4G', 'VoLTE'],
bands: ['LTE 1800', 'LTE 2600'],
roamingAgreements: ['US', 'EU', 'APAC'],
coverage: {
area: ['Nationwide', 'Urban', 'Suburban'],
quality: Math.random() > 0.5 ? 'excellent' : 'good'
}
}
const fraudIndicators: PhoneNumberAnalysis['fraudIndicators'] = {
velocityCheck: Math.random() > 0.95, // 5% suspicious velocity
patternAnalysis: Math.random() > 0.98, // 2% suspicious pattern
blacklisted: Math.random() > 0.99, // 1% blacklisted
suspiciousActivity: Math.random() > 0.97, // 3% suspicious
riskFactors: intelligence.riskScore > 70 ? ['High risk score'] : []
}
return { intelligence, network, fraudIndicators }
}
private determineNetworkType(mcc: string, mnc: string): PhoneNumberAnalysis['carrier']['networkType'] {
// In production, use carrier database to determine network type
// For demo, return based on MCC
if (mcc === '310' || mcc === '311' || mcc === '312') {
return 'cdma'
}
return 'gsm'
}
private getCarrierBands(mcc: string, mnc: string): string[] {
// In production, use carrier database to get supported bands
// For demo, return common bands
return ['GSM 900', 'GSM 1800', 'UMTS 2100', 'LTE 1800', 'LTE 2600']
}
private validateChecksum(phoneNumber: string): boolean {
// Simplified checksum validation
// In production, implement proper checksum algorithms per country
if (phoneNumber.length < 10) return false
// Simple modulo check (not real checksum)
const digits = phoneNumber.split('').map(Number)
const sum = digits.reduce((acc, digit, index) => acc + digit * (index + 1), 0)
return sum % 10 === 0
}
private getCachedAnalysis(phoneNumber: string): PhoneNumberAnalysis | null {
const cached = this.numberCache.get(phoneNumber)
if (cached && Date.now() - this.config.cacheDuration < cached.intelligence.lastSeen) {
return cached
}
if (cached) {
this.numberCache.delete(phoneNumber)
}
return null
}
private cacheAnalysis(phoneNumber: string, analysis: PhoneNumberAnalysis): void {
this.numberCache.set(phoneNumber, analysis)
// Maintain cache size
if (this.numberCache.size > 50000) {
const entries = Array.from(this.numberCache.entries())
const oldestKey = entries.sort(([, a], [, b]) => a.intelligence.lastSeen - b.intelligence.lastSeen)[0][0]
this.numberCache.delete(oldestKey)
}
}
// Fraud detection analysis
async detectFraud(phoneNumber: string): Promise<FraudDetectionResult> {
const cached = this.fraudCache.get(phoneNumber)
if (cached && Date.now() - 24 * 60 * 60 * 1000 < Date.now()) { // 24 hour cache
return cached
}
try {
const analysis = await this.analyzePhoneNumber(phoneNumber)
const indicators: string[] = []
const recommendations: string[] = []
// Analyze risk indicators
if (analysis.fraudIndicators.blacklisted) {
indicators.push('Number is blacklisted')
recommendations.push('Block transaction immediately')
}
if (analysis.fraudIndicators.velocityCheck) {
indicators.push('Suspicious velocity pattern')
recommendations.push('Require additional verification')
}
if (analysis.fraudIndicators.suspiciousActivity) {
indicators.push('Suspicious activity detected')
recommendations.push('Manual review required')
}
if (analysis.intelligence.riskScore > 80) {
indicators.push('High risk score')
recommendations.push('Enhanced security measures required')
}
if (analysis.intelligence.isRoaming) {
indicators.push('International roaming detected')
recommendations.push('Verify location consistency')
}
const riskScore = Math.max(
analysis.intelligence.riskScore,
analysis.fraudIndicators.blacklisted ? 100 : 0,
analysis.fraudIndicators.velocityCheck ? 85 : 0,
analysis.fraudIndicators.suspiciousActivity ? 90 : 0
)
const riskLevel = riskScore > 90 ? 'critical' :
riskScore > 70 ? 'high' :
riskScore > 40 ? 'medium' : 'low'
const result: FraudDetectionResult = {
phoneNumber,
riskScore,
riskLevel,
indicators,
recommendations,
blocked: riskScore > 95,
requiresReview: riskScore > 70
}
this.fraudCache.set(phoneNumber, result)
return result
} catch (error) {
console.error('Fraud detection failed:', error)
return {
phoneNumber,
riskScore: 100,
riskLevel: 'critical',
indicators: ['Analysis failed'],
recommendations: ['Block transaction'],
blocked: true,
requiresReview: true
}
}
}
// Batch analysis for multiple numbers
async analyzePhoneNumbersBatch(phoneNumbers: string[]): Promise<Map<string, PhoneNumberAnalysis>> {
const results = new Map<string, PhoneNumberAnalysis>()
// Process in batches of 20
const batchSize = 20
for (let i = 0; i < phoneNumbers.length; i += batchSize) {
const batch = phoneNumbers.slice(i, i + batchSize)
const batchPromises = batch.map(async (phoneNumber) => {
try {
const analysis = await this.analyzePhoneNumber(phoneNumber)
return { phoneNumber, analysis }
} catch (error) {
console.error(`Batch analysis failed for ${phoneNumber}:`, error)
return { phoneNumber, analysis: null }
}
})
const batchResults = await Promise.all(batchPromises)
batchResults.forEach(({ phoneNumber, analysis }) => {
if (analysis) {
results.set(phoneNumber, analysis)
}
})
// Small delay between batches
if (i + batchSize < phoneNumbers.length) {
await new Promise(resolve => setTimeout(resolve, 200))
}
}
return results
}
// Get intelligence statistics
getIntelligenceStats(): {
totalAnalyses: number
validNumbers: number
activeSubscribers: number
roamingSubscribers: number
averageRiskScore: number
topRiskFactors: Array<{ factor: string; count: number }>
} {
const analyses = Array.from(this.numberCache.values())
const total = analyses.length
if (total === 0) {
return {
totalAnalyses: 0,
validNumbers: 0,
activeSubscribers: 0,
roamingSubscribers: 0,
averageRiskScore: 0,
topRiskFactors: []
}
}
const validNumbers = analyses.filter(a => a.validation.isValid).length
const activeSubscribers = analyses.filter(a => a.intelligence.isActive).length
const roamingSubscribers = analyses.filter(a => a.intelligence.isRoaming).length
const averageRiskScore = analyses.reduce((sum, a) => sum + a.intelligence.riskScore, 0) / total
// Count risk factors
const riskFactors = new Map<string, number>()
analyses.forEach(analysis => {
analysis.fraudIndicators.riskFactors.forEach(factor => {
const count = riskFactors.get(factor) || 0
riskFactors.set(factor, count + 1)
})
})
const topRiskFactors = Array.from(riskFactors.entries())
.sort(([, a], [, b]) => b - a)
.slice(0, 10)
.map(([factor, count]) => ({ factor, count }))
return {
totalAnalyses: total,
validNumbers,
activeSubscribers,
roamingSubscribers,
averageRiskScore,
topRiskFactors
}
}
}
// Enhanced phone number validation with carrier intelligence
class EnhancedPhoneValidator {
private carrierEngine: CarrierIntelligenceEngine
private validationCache: Map<string, {
result: PhoneNumberAnalysis
expires: number
}> = new Map()
constructor() {
const config: CarrierIntelligenceConfig = {
enableHLRLookup: true,
enableNetworkAnalysis: true,
enableFraudDetection: true,
cacheResults: true,
cacheDuration: 24 * 60 * 60 * 1000, // 24 hours
maxRetries: 3
}
this.carrierEngine = new CarrierIntelligenceEngine(config)
}
async validatePhoneNumber(phoneNumber: string, countryCode?: string): Promise<{
isValid: boolean
analysis: PhoneNumberAnalysis
fraudCheck?: FraudDetectionResult
recommendation: string
}> {
// Check cache first
const cached = this.getCachedValidation(phoneNumber)
if (cached) {
return {
isValid: cached.result.validation.isValid,
analysis: cached.result,
recommendation: this.generateRecommendation(cached.result)
}
}
try {
// Perform comprehensive analysis
const analysis = await this.carrierEngine.analyzePhoneNumber(phoneNumber, countryCode)
// Perform fraud detection if enabled
let fraudCheck: FraudDetectionResult | undefined
if (this.carrierEngine['config'].enableFraudDetection) {
fraudCheck = await this.carrierEngine.detectFraud(phoneNumber)
}
const result = {
isValid: analysis.validation.isValid && analysis.intelligence.confidence > 50,
analysis,
fraudCheck,
recommendation: this.generateRecommendation(analysis, fraudCheck)
}
// Cache result for 24 hours
this.cacheValidation(phoneNumber, result)
return result
} catch (error) {
console.error('Enhanced phone validation failed:', error)
return {
isValid: false,
analysis: {} as PhoneNumberAnalysis,
recommendation: 'Validation failed - manual review required'
}
}
}
private getCachedValidation(phoneNumber: string): PhoneNumberAnalysis | null {
const cached = this.validationCache.get(phoneNumber)
if (cached && cached.expires > Date.now()) {
return cached.result
}
if (cached) {
this.validationCache.delete(phoneNumber)
}
return null
}
private cacheValidation(phoneNumber: string, result: any): void {
this.validationCache.set(phoneNumber, {
result: result.analysis,
expires: Date.now() + 24 * 60 * 60 * 1000 // 24 hours
})
// Maintain cache size
if (this.validationCache.size > 100000) {
const entries = Array.from(this.validationCache.entries())
const oldestKey = entries.sort(([, a], [, b]) => a.expires - b.expires)[0][0]
this.validationCache.delete(oldestKey)
}
}
private generateRecommendation(
analysis: PhoneNumberAnalysis,
fraudCheck?: FraudDetectionResult
): string {
if (!analysis.validation.isValid) {
return 'Invalid phone number format - please check and retry'
}
if (analysis.intelligence.riskScore > 80) {
return 'High risk number detected - enhanced verification required'
}
if (analysis.intelligence.isRoaming) {
return 'Roaming number detected - verify international compatibility'
}
if (analysis.intelligence.isPorted) {
return 'Ported number detected - carrier information may be outdated'
}
if (fraudCheck?.blocked) {
return 'Number blocked due to fraud indicators - transaction denied'
}
if (fraudCheck?.requiresReview) {
return 'Number requires manual review before processing'
}
return 'Phone number validated successfully'
}
// Batch validation for multiple numbers
async validatePhoneNumbersBatch(phoneNumbers: string[]): Promise<Map<string, any>> {
return this.carrierEngine.analyzePhoneNumbersBatch(phoneNumbers)
}
getValidationStats(): {
totalValidations: number
validNumbers: number
highRiskNumbers: number
roamingNumbers: number
averageConfidence: number
} {
return this.carrierEngine.getIntelligenceStats()
}
}
// Initialize enhanced phone validator
const enhancedPhoneValidator = new EnhancedPhoneValidator()
// Enhanced phone validation endpoints
app.post('/api/validate-phone-enhanced', async (req, res) => {
try {
const { phoneNumber, countryCode } = req.body
if (!phoneNumber) {
return res.status(400).json({ error: 'phoneNumber required' })
}
const result = await enhancedPhoneValidator.validatePhoneNumber(phoneNumber, countryCode)
res.json({
validation: result,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Enhanced phone validation error:', error)
res.status(500).json({ error: 'Enhanced validation failed' })
}
})
// Batch phone validation endpoint
app.post('/api/validate-phones-batch', async (req, res) => {
try {
const { phoneNumbers } = req.body
if (!Array.isArray(phoneNumbers)) {
return res.status(400).json({ error: 'phoneNumbers array required' })
}
const results = await enhancedPhoneValidator.validatePhoneNumbersBatch(phoneNumbers)
res.json({
results: Object.fromEntries(results.entries()),
count: results.size,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Batch phone validation error:', error)
res.status(500).json({ error: 'Batch validation failed' })
}
})
// Phone validation statistics endpoint
app.get('/api/phone-validation-stats', (req, res) => {
try {
const stats = enhancedPhoneValidator.getValidationStats()
res.json({
statistics: stats,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Statistics retrieval error:', error)
res.status(500).json({ error: 'Statistics retrieval failed' })
}
})
console.log('Enhanced Phone Validation with Carrier Intelligence initialized')Fraud Detection Integration
Integrating fraud detection with carrier intelligence provides comprehensive security for phone-based transactions.
Risk Assessment Framework
Velocity Analysis
- Track request frequency per number
- Detect burst patterns indicating automation
- Implement progressive delays for suspicious activity
- Alert thresholds: >10 requests/minute, >100 requests/hour
Pattern Recognition
- Analyze number sequences for bulk generation
- Detect sequential number patterns
- Identify common fraud number ranges
- Flag numbers with suspicious formatting
Blacklist Management
- Maintain real-time blacklist database
- Cross-reference with known fraud numbers
- Update blacklist from multiple sources
- Implement whitelist for trusted numbers
Implementation Example
// Fraud detection integration with carrier intelligence
class FraudDetectionService {
private riskThresholds = {
velocity: 10, // requests per minute
pattern: 0.8, // pattern similarity score
blacklist: true, // any blacklist match
roaming: 0.7 // roaming risk score
}
async assessFraudRisk(phoneNumber: string, context: TransactionContext): Promise<FraudRiskAssessment> {
const [carrierInfo, velocityData, patternAnalysis] = await Promise.all([
this.getCarrierIntelligence(phoneNumber),
this.analyzeVelocity(phoneNumber, context),
this.analyzePattern(phoneNumber)
])
const riskFactors = []
let riskScore = 0
// Velocity check
if (velocityData.requestsPerMinute > this.riskThresholds.velocity) {
riskFactors.push('High velocity detected')
riskScore += 30
}
// Pattern analysis
if (patternAnalysis.similarityScore > this.riskThresholds.pattern) {
riskFactors.push('Suspicious pattern detected')
riskScore += 25
}
// Blacklist check
if (await this.isBlacklisted(phoneNumber)) {
riskFactors.push('Number is blacklisted')
riskScore += 50
}
// Roaming analysis
if (carrierInfo.isRoaming && carrierInfo.roamingRiskScore > this.riskThresholds.roaming) {
riskFactors.push('High-risk roaming detected')
riskScore += 20
}
return {
phoneNumber,
riskScore: Math.min(riskScore, 100),
riskLevel: this.calculateRiskLevel(riskScore),
riskFactors,
recommendation: this.generateRecommendation(riskScore, riskFactors),
requiresReview: riskScore > 70,
blocked: riskScore > 90
}
}
}Performance Optimization Strategies
Optimizing carrier intelligence systems requires careful attention to caching, rate limiting, and resource management.
Caching Strategies
Multi-Level Caching
- L1: In-memory cache (Redis) - 1-5 minutes TTL
- L2: Database cache - 1-24 hours TTL
- L3: CDN cache - 1-7 days TTL
Cache Invalidation
- Time-based expiration
- Event-driven invalidation
- Manual cache refresh
- Stale-while-revalidate pattern
Rate Limiting
Provider Rate Limits
- HLR providers: 100-1000 requests/second
- Carrier databases: 50-500 requests/second
- Fraud detection APIs: 10-100 requests/second
Implementation
class RateLimiter {
private limits = new Map<string, { count: number; resetTime: number }>()
async checkLimit(provider: string, limit: number): Promise<boolean> {
const now = Date.now()
const current = this.limits.get(provider) || { count: 0, resetTime: now + 60000 }
if (now > current.resetTime) {
current.count = 0
current.resetTime = now + 60000
}
if (current.count >= limit) {
return false
}
current.count++
this.limits.set(provider, current)
return true
}
}Implementation Best Practices
Architecture Design
Microservices Approach
- Separate HLR lookup service
- Independent fraud detection service
- Dedicated caching layer
- API gateway for rate limiting
Error Handling
- Graceful degradation on service failures
- Circuit breaker pattern for external APIs
- Retry logic with exponential backoff
- Comprehensive logging and monitoring
Security Considerations
Data Protection
- Encrypt sensitive data in transit and at rest
- Implement proper access controls
- Regular security audits
- Compliance with data protection regulations
API Security
- Authentication and authorization
- Rate limiting per user/IP
- Input validation and sanitization
- Audit logging for all requests
Monitoring and Alerting
Key Metrics
- Request latency (p50, p95, p99)
- Error rates by service
- Cache hit ratios
- Fraud detection accuracy
Alerting Thresholds
- Latency > 2 seconds
- Error rate > 5%
- Cache hit ratio < 80%
- Fraud false positive rate > 10%
Conclusion
Carrier intelligence systems provide essential capabilities for modern applications requiring phone number validation and fraud detection. Success depends on:
- Robust architecture with proper error handling and caching
- Comprehensive fraud detection with multiple risk assessment layers
- Performance optimization through intelligent caching and rate limiting
- Security-first approach with proper data protection and access controls
Implement carrier intelligence with our professional solutions, designed for enterprise-scale performance and reliability.