0
# Short Numbers
1
2
Support for emergency numbers, short codes, and special service numbers with cost information and regional validation. Short numbers are typically 3-6 digit numbers used for emergency services, directory assistance, and other special services.
3
4
## Capabilities
5
6
### Short Number Validation
7
8
Validate whether short numbers are valid for emergency services, directory assistance, and other special services.
9
10
```python { .api }
11
def is_valid_short_number(numobj: PhoneNumber) -> bool:
12
"""
13
Check if a short number is valid.
14
15
A valid short number is one that is recognized as providing
16
a specific service in at least one region.
17
18
Parameters:
19
- numobj: PhoneNumber object containing the short number
20
21
Returns:
22
True if the short number is valid, False otherwise
23
"""
24
25
def is_valid_short_number_for_region(short_numobj: PhoneNumber,
26
region_dialing_from: str) -> bool:
27
"""
28
Check if a short number is valid for a specific region.
29
30
Parameters:
31
- short_numobj: PhoneNumber object containing the short number
32
- region_dialing_from: Two-letter region code where number would be dialed
33
34
Returns:
35
True if valid for the specified region, False otherwise
36
"""
37
```
38
39
### Short Number Possibility
40
41
Check if short numbers are possible (have valid lengths) without full validation.
42
43
```python { .api }
44
def is_possible_short_number(numobj: PhoneNumber) -> bool:
45
"""
46
Check if a short number is possible.
47
48
This is a quicker check than full validation - verifies that
49
the short number length is appropriate for some region.
50
51
Parameters:
52
- numobj: PhoneNumber object containing the short number
53
54
Returns:
55
True if the short number could possibly be valid, False otherwise
56
"""
57
58
def is_possible_short_number_for_region(short_numobj: PhoneNumber,
59
region_dialing_from: str) -> bool:
60
"""
61
Check if a short number is possible for a specific region.
62
63
Parameters:
64
- short_numobj: PhoneNumber object containing the short number
65
- region_dialing_from: Region from which the number would be dialed
66
67
Returns:
68
True if possible for the specified region, False otherwise
69
"""
70
```
71
72
### Emergency Number Detection
73
74
Identify and validate emergency service numbers.
75
76
```python { .api }
77
def is_emergency_number(number: str, region_code: str) -> bool:
78
"""
79
Check if a number string is an emergency number for a region.
80
81
Parameters:
82
- number: Phone number string to check
83
- region_code: Two-letter region code for validation context
84
85
Returns:
86
True if the number connects to emergency services, False otherwise
87
"""
88
89
def connects_to_emergency_number(number: str, region_code: str) -> bool:
90
"""
91
Check if dialing a number connects to emergency services.
92
93
This may return True for numbers that are not emergency numbers
94
themselves but would route to emergency services when dialed.
95
96
Parameters:
97
- number: Phone number string to check
98
- region_code: Region code for dialing context
99
100
Returns:
101
True if dialing this number connects to emergency services
102
"""
103
```
104
105
### Cost Information
106
107
Determine the cost associated with calling short numbers.
108
109
```python { .api }
110
class ShortNumberCost:
111
"""Cost categories for short numbers."""
112
113
TOLL_FREE = 0
114
"""Short number is free to call."""
115
116
STANDARD_RATE = 1
117
"""Short number is charged at standard rate."""
118
119
PREMIUM_RATE = 2
120
"""Short number is charged at premium rate."""
121
122
UNKNOWN_COST = 3
123
"""Cost of short number is unknown."""
124
125
def expected_cost(numobj: PhoneNumber) -> ShortNumberCost:
126
"""
127
Get the expected cost of calling a short number.
128
129
Parameters:
130
- numobj: PhoneNumber object containing the short number
131
132
Returns:
133
ShortNumberCost indicating the expected charge category
134
"""
135
136
def expected_cost_for_region(numobj: PhoneNumber,
137
region_dialing_from: str) -> ShortNumberCost:
138
"""
139
Get expected cost of calling a short number from a specific region.
140
141
Parameters:
142
- numobj: PhoneNumber object containing the short number
143
- region_dialing_from: Region from which the call would be made
144
145
Returns:
146
ShortNumberCost for the specific region context
147
"""
148
```
149
150
### Carrier-Specific Numbers
151
152
Check if short numbers are specific to particular carriers.
153
154
```python { .api }
155
def is_carrier_specific(numobj: PhoneNumber) -> bool:
156
"""
157
Check if a short number is carrier-specific.
158
159
Carrier-specific numbers only work when dialed from phones
160
on specific mobile networks or carriers.
161
162
Parameters:
163
- numobj: PhoneNumber object containing the short number
164
165
Returns:
166
True if the number is carrier-specific, False otherwise
167
"""
168
169
def is_carrier_specific_for_region(numobj: PhoneNumber,
170
region_dialing_from: str) -> bool:
171
"""
172
Check if a short number is carrier-specific for a region.
173
174
Parameters:
175
- numobj: PhoneNumber object containing the short number
176
- region_dialing_from: Region to check carrier specificity for
177
178
Returns:
179
True if carrier-specific in the region, False otherwise
180
"""
181
```
182
183
### SMS Services
184
185
Check if short numbers provide SMS services.
186
187
```python { .api }
188
def is_sms_service_for_region(numobj: PhoneNumber, region_dialing_from: str) -> bool:
189
"""
190
Check if a short number provides SMS services for a region.
191
192
Parameters:
193
- numobj: PhoneNumber object containing the short number
194
- region_dialing_from: Region to check SMS service availability
195
196
Returns:
197
True if the number provides SMS services, False otherwise
198
"""
199
```
200
201
### Supported Regions
202
203
Access information about regions that support short number services.
204
205
```python { .api }
206
SUPPORTED_SHORT_REGIONS: list
207
"""
208
List of region codes that have short number support.
209
210
These are regions for which the library has metadata
211
about emergency numbers, directory services, and other
212
short number services.
213
"""
214
```
215
216
## Usage Examples
217
218
### Emergency Number Validation
219
220
```python
221
import phonenumbers
222
223
def check_emergency_numbers():
224
"""Check emergency numbers for various regions."""
225
emergency_tests = [
226
("911", "US"), # US emergency
227
("999", "GB"), # UK emergency
228
("112", "DE"), # EU emergency
229
("000", "AU"), # Australian emergency
230
("110", "JP"), # Japanese police
231
("119", "JP"), # Japanese fire/ambulance
232
]
233
234
print("Emergency Number Validation:")
235
for number, region in emergency_tests:
236
is_emergency = phonenumbers.is_emergency_number(number, region)
237
connects_emergency = phonenumbers.connects_to_emergency_number(number, region)
238
239
print(f" {number} in {region}:")
240
print(f" Is emergency number: {is_emergency}")
241
print(f" Connects to emergency: {connects_emergency}")
242
243
# Example usage
244
check_emergency_numbers()
245
```
246
247
### Short Number Analysis
248
249
```python
250
import phonenumbers
251
from phonenumbers import ShortNumberCost
252
253
def analyze_short_number(number_str, region):
254
"""Comprehensive analysis of a short number."""
255
try:
256
# Parse as short number (no country code)
257
number = phonenumbers.parse(number_str, region)
258
259
# Basic validation
260
is_valid = phonenumbers.is_valid_short_number_for_region(number, region)
261
is_possible = phonenumbers.is_possible_short_number_for_region(number, region)
262
263
# Emergency services
264
is_emergency = phonenumbers.is_emergency_number(number_str, region)
265
connects_emergency = phonenumbers.connects_to_emergency_number(number_str, region)
266
267
# Cost information
268
cost = phonenumbers.expected_cost_for_region(number, region)
269
cost_names = {
270
ShortNumberCost.TOLL_FREE: "Toll Free",
271
ShortNumberCost.STANDARD_RATE: "Standard Rate",
272
ShortNumberCost.PREMIUM_RATE: "Premium Rate",
273
ShortNumberCost.UNKNOWN_COST: "Unknown Cost"
274
}
275
276
# Carrier and SMS info
277
is_carrier_specific = phonenumbers.is_carrier_specific_for_region(number, region)
278
provides_sms = phonenumbers.is_sms_service_for_region(number, region)
279
280
return {
281
'number': number_str,
282
'region': region,
283
'is_valid': is_valid,
284
'is_possible': is_possible,
285
'is_emergency': is_emergency,
286
'connects_to_emergency': connects_emergency,
287
'cost': cost_names.get(cost, "Unknown"),
288
'is_carrier_specific': is_carrier_specific,
289
'provides_sms': provides_sms
290
}
291
292
except phonenumbers.NumberParseException as e:
293
return {
294
'number': number_str,
295
'region': region,
296
'error': str(e)
297
}
298
299
# Example usage
300
short_numbers = [
301
("911", "US"), # US emergency
302
("411", "US"), # US directory assistance
303
("611", "US"), # US customer service
304
("999", "GB"), # UK emergency
305
("100", "GB"), # UK operator
306
("112", "DE"), # EU-wide emergency
307
]
308
309
print("Short Number Analysis:")
310
for number, region in short_numbers:
311
analysis = analyze_short_number(number, region)
312
313
if 'error' in analysis:
314
print(f"\n{number} ({region}): Parse Error - {analysis['error']}")
315
continue
316
317
print(f"\n{number} ({region}):")
318
print(f" Valid: {analysis['is_valid']}")
319
print(f" Possible: {analysis['is_possible']}")
320
print(f" Emergency: {analysis['is_emergency']}")
321
print(f" Cost: {analysis['cost']}")
322
print(f" Carrier Specific: {analysis['is_carrier_specific']}")
323
print(f" SMS Service: {analysis['provides_sms']}")
324
```
325
326
### Emergency Service Directory
327
328
```python
329
import phonenumbers
330
331
class EmergencyServiceDirectory:
332
"""Directory of emergency services by region."""
333
334
def __init__(self):
335
self.known_emergency_patterns = {
336
# Common emergency numbers to test
337
"US": ["911", "112"],
338
"GB": ["999", "112"],
339
"DE": ["110", "112", "116117"],
340
"FR": ["15", "17", "18", "112"],
341
"AU": ["000", "112"],
342
"JP": ["110", "119"],
343
"CN": ["110", "119", "120"],
344
"IN": ["100", "101", "102", "108", "112"],
345
"BR": ["190", "193", "199"],
346
"CA": ["911", "112"]
347
}
348
349
def get_emergency_numbers(self, region_code):
350
"""Get confirmed emergency numbers for a region."""
351
emergency_numbers = []
352
353
if region_code not in phonenumbers.SUPPORTED_SHORT_REGIONS:
354
return {"error": f"Short numbers not supported for region {region_code}"}
355
356
# Test known patterns
357
test_numbers = self.known_emergency_patterns.get(region_code, [])
358
359
for number in test_numbers:
360
if phonenumbers.is_emergency_number(number, region_code):
361
emergency_numbers.append({
362
'number': number,
363
'connects_to_emergency': phonenumbers.connects_to_emergency_number(number, region_code)
364
})
365
366
return {
367
'region': region_code,
368
'emergency_numbers': emergency_numbers
369
}
370
371
def generate_emergency_guide(self, regions):
372
"""Generate emergency number guide for multiple regions."""
373
guide = {}
374
375
for region in regions:
376
info = self.get_emergency_numbers(region)
377
if 'error' not in info:
378
guide[region] = info['emergency_numbers']
379
380
return guide
381
382
def format_emergency_guide(self, guide):
383
"""Format emergency guide as readable text."""
384
output = ["EMERGENCY NUMBERS BY REGION", "=" * 30]
385
386
for region, numbers in guide.items():
387
output.append(f"\n{region}:")
388
if numbers:
389
for num_info in numbers:
390
status = "✓" if num_info['connects_to_emergency'] else "?"
391
output.append(f" {status} {num_info['number']}")
392
else:
393
output.append(" No emergency numbers found")
394
395
return "\n".join(output)
396
397
# Example usage
398
directory = EmergencyServiceDirectory()
399
400
# Get emergency numbers for specific regions
401
regions_to_check = ["US", "GB", "DE", "JP", "AU"]
402
emergency_guide = directory.generate_emergency_guide(regions_to_check)
403
404
print("Emergency Services Directory:")
405
print(directory.format_emergency_guide(emergency_guide))
406
407
# Detailed analysis for US
408
print("\n" + "=" * 50)
409
print("Detailed US Emergency Number Analysis:")
410
us_info = directory.get_emergency_numbers("US")
411
for num_info in us_info['emergency_numbers']:
412
number = num_info['number']
413
analysis = analyze_short_number(number, "US")
414
print(f"\n{number}:")
415
for key, value in analysis.items():
416
if key not in ['number', 'region']:
417
print(f" {key}: {value}")
418
```
419
420
### SMS Short Code Validation
421
422
```python
423
import phonenumbers
424
425
class SMSShortCodeValidator:
426
"""Validator for SMS short codes and services."""
427
428
def __init__(self):
429
self.common_sms_patterns = {
430
"US": ["22", "737", "4INFO", "GOOGLE", "40404"], # Common US SMS codes
431
"GB": ["61998", "88088"], # Common UK SMS codes
432
"DE": ["1212", "8888"], # Common German SMS codes
433
}
434
435
def validate_sms_code(self, code, region):
436
"""Validate if a code provides SMS services."""
437
try:
438
# Try to parse as short number
439
number = phonenumbers.parse(code, region)
440
441
# Check if it's a valid short number
442
is_valid = phonenumbers.is_valid_short_number_for_region(number, region)
443
if not is_valid:
444
return {
445
'code': code,
446
'region': region,
447
'is_valid': False,
448
'reason': 'Not a valid short number'
449
}
450
451
# Check SMS capability
452
provides_sms = phonenumbers.is_sms_service_for_region(number, region)
453
cost = phonenumbers.expected_cost_for_region(number, region)
454
is_carrier_specific = phonenumbers.is_carrier_specific_for_region(number, region)
455
456
return {
457
'code': code,
458
'region': region,
459
'is_valid': True,
460
'provides_sms': provides_sms,
461
'cost': cost,
462
'is_carrier_specific': is_carrier_specific
463
}
464
465
except phonenumbers.NumberParseException:
466
return {
467
'code': code,
468
'region': region,
469
'is_valid': False,
470
'reason': 'Parse error'
471
}
472
473
def scan_region_sms_codes(self, region):
474
"""Scan common SMS codes for a region."""
475
if region not in self.common_sms_patterns:
476
return {'error': f'No SMS patterns defined for {region}'}
477
478
results = []
479
for code in self.common_sms_patterns[region]:
480
validation = self.validate_sms_code(code, region)
481
results.append(validation)
482
483
return {
484
'region': region,
485
'codes_tested': len(self.common_sms_patterns[region]),
486
'results': results
487
}
488
489
# Example usage
490
validator = SMSShortCodeValidator()
491
492
print("SMS Short Code Validation:")
493
for region in ["US", "GB", "DE"]:
494
print(f"\n{region} SMS Codes:")
495
scan_result = validator.scan_region_sms_codes(region)
496
497
if 'error' in scan_result:
498
print(f" {scan_result['error']}")
499
continue
500
501
for result in scan_result['results']:
502
if result['is_valid']:
503
sms_status = "✓" if result.get('provides_sms') else "✗"
504
carrier_status = "(carrier-specific)" if result.get('is_carrier_specific') else ""
505
print(f" {result['code']}: Valid, SMS {sms_status}, Cost: {result.get('cost')} {carrier_status}")
506
else:
507
print(f" {result['code']}: Invalid - {result.get('reason', 'Unknown')}")
508
```
509
510
### Regional Short Number Support
511
512
```python
513
import phonenumbers
514
515
def analyze_short_number_support():
516
"""Analyze which regions support short number functionality."""
517
all_regions = phonenumbers.supported_regions()
518
short_regions = set(phonenumbers.SUPPORTED_SHORT_REGIONS)
519
520
print(f"Total regions supported: {len(all_regions)}")
521
print(f"Regions with short number support: {len(short_regions)}")
522
print(f"Coverage: {len(short_regions)/len(all_regions)*100:.1f}%")
523
524
# Show some regions with short number support
525
print(f"\nRegions with short number support (first 20):")
526
for region in sorted(list(short_regions))[:20]:
527
print(f" {region}")
528
529
# Show regions without short number support
530
no_short_support = all_regions - short_regions
531
print(f"\nRegions without short number support (first 10):")
532
for region in sorted(list(no_short_support))[:10]:
533
print(f" {region}")
534
535
def test_emergency_coverage():
536
"""Test emergency number coverage across regions."""
537
emergency_coverage = {}
538
test_numbers = ["911", "999", "112", "000", "110", "119"]
539
540
for region in phonenumbers.SUPPORTED_SHORT_REGIONS[:10]: # Test first 10
541
emergency_coverage[region] = []
542
543
for number in test_numbers:
544
if phonenumbers.is_emergency_number(number, region):
545
emergency_coverage[region].append(number)
546
547
print("\nEmergency Number Coverage (first 10 regions):")
548
for region, numbers in emergency_coverage.items():
549
if numbers:
550
print(f" {region}: {', '.join(numbers)}")
551
else:
552
print(f" {region}: No common emergency numbers found")
553
554
# Example usage
555
print("=== Short Number Support Analysis ===")
556
analyze_short_number_support()
557
558
print("\n=== Emergency Number Coverage ===")
559
test_emergency_coverage()
560
```
561
562
## Important Notes
563
564
### Regional Variations
565
566
Short numbers vary significantly by region:
567
- **US**: 911 (emergency), 411 (directory), 611 (customer service)
568
- **UK**: 999 (emergency), 100 (operator), 118xxx (directory)
569
- **EU**: 112 (pan-European emergency)
570
- **Japan**: 110 (police), 119 (fire/ambulance)
571
572
### Cost Considerations
573
574
Always check cost before directing users to dial short numbers:
575
- **Emergency numbers** are typically toll-free
576
- **Directory services** may charge premium rates
577
- **SMS short codes** can have varying costs
578
579
### Carrier Dependencies
580
581
Some short numbers only work with specific carriers or in specific circumstances. Always validate carrier-specific restrictions before implementing automated dialing of short numbers.