I’m trying to validate a mobile number, the following is what I have done so far, but it does not appear to work.
I need it to raise a validation error when the value passed does not look like a mobile number. Mobile numbers can be 10 to 14 digits long, start with 0 or 7, and could have 44 or +44 added to them.
def validate_mobile(value):
""" Raise a ValidationError if the value looks like a mobile telephone number.
"""
rule = re.compile(r'/^[0-9]{10,14}$/')
if not rule.search(value):
msg = u"Invalid mobile number."
raise ValidationError(msg)
SuperStormer
4,8625 gold badges23 silver badges34 bronze badges
asked Apr 21, 2013 at 19:04
5
I would recommend to use the phonenumbers package which is a python port of Google’s libphonenumber which includes a data set of mobile carriers now:
import phonenumbers
from phonenumbers import carrier
from phonenumbers.phonenumberutil import number_type
number = "+49 176 1234 5678"
carrier._is_mobile(number_type(phonenumbers.parse(number)))
This will return True in case number is a mobile number or False otherwise. Note that the number must be a valid international number or an exception will be thrown. You can also use phonenumbers to parse phonenumber given a region hint.
answered Feb 6, 2014 at 16:22
davidndavidn
7827 silver badges13 bronze badges
4
The following regex matches your description
r'^(?:+?44)?[07]d{9,13}$'
answered Apr 21, 2013 at 19:11
MikeMMikeM
13k2 gold badges32 silver badges47 bronze badges
2
I would try something like:
re.compile(r'^+?(44)?(0|7)d{9,13}$')
You would want to first remove any spaces, hyphens, or parentheses though.
answered Apr 21, 2013 at 19:09
dgeldgel
16.1k8 gold badges58 silver badges75 bronze badges
1
These won’t validate +44 numbers as required. Follow update: John Brown’s link and try something like this:
def validate_not_mobile(value):
rule = re.compile(r'(^[+0-9]{1,3})*([0-9]{10,11}$)')
if rule.search(value):
msg = u"You cannot add mobile numbers."
raise ValidationError(msg)
answered Apr 21, 2013 at 20:00
Glyn JacksonGlyn Jackson
8,2084 gold badges27 silver badges52 bronze badges
3
import phonenumbers
from phonenumbers import carrier, timezone, geocoder
from phonenumbers.phonenumberutil import number_type
number = "+911234567890"
print(carrier._is_mobile(number_type(phonenumbers.parse(number))))
print(phonenumbers.parse("+911234567890"))
my_number = phonenumbers.parse("+911234567890")
print(carrier.name_for_number(my_number, "en"))
print(timezone.time_zones_for_number(my_number))
print(geocoder.description_for_number(my_number, "en"))
print(phonenumbers.is_valid_number(my_number))
print(phonenumbers.is_possible_number(my_number))
The reason is that the is_possible_number() method makes a quick guess on the phone number’s validity by checking the length of the parsed number, while the is_valid_number() method runs a full validation by checking the length, phone number prefix, and region.
answered Nov 5, 2021 at 6:26
MRUNAL MUNOTMRUNAL MUNOT
3871 gold badge5 silver badges18 bronze badges
You can create a validate function using phonenumbers package
for example:
import phonenumbers
def validate_phone_number(potential_number: str, country_code: str) -> bool:
try:
phone_number_obj = phonenumbers.parse(potential_number, country_code)
except phonenumbers.phonenumberutil.NumberParseException:
return False
if not phonenumbers.is_valid_number(phone_number_obj):
return False
return True
answered Dec 18, 2022 at 13:58
Alon BaradAlon Barad
1,3151 gold badge13 silver badges23 bronze badges
Python validation mobile number for sololearn
str = input()
import re
if len(str)==8:
pattern=r"[981][^.......$]"
match = re.match(pattern,str)
if match:
print("Valid")
else:
print("Invalid")
else:
print("Invalid")
answered Jan 7, 2021 at 8:46
1
- Validate Phone Numbers in Python
- Use the
Phonenumbers
Library in Python - Parse Phone Numbers With Python
Phonenumbers
Library - Validate Phone Numbers Using the
is_possible_number()
Method - Validate Phone Numbers Using the
is_valid_number()
Method - Use the
description_for_number()
Method in theGeocoder
Class to Find the Phone Number Location - Use the
name_for_number()
Method in theCarrier
Class to Find the Phone Number Carrier - Validate Phone Numbers and Get Additional Information Using Python
This Python article will show how we can validate phone numbers using Python’s phonenumbers
library. We will learn to use Python to validate phone numbers and then format them for display according to region, country, continent, and carrier.
We will start with a simple example and move to a complex one. So let’s get started and let Python validate and format phone numbers.
Validate Phone Numbers in Python
Verifying and validating the correctness of phone numbers can be very challenging. A phone number’s format can change depending on our country.
Even within the same nation, there may be significant differences. Some countries use the same country code, while others use multiple country codes.
Some countries even use the same country code more than once.
An illustration in Google’s libphonenumber
repository on GitHub demonstrates that the United States of America, Canada, and the Caribbean islands all use the same international dialing code of +1.
The phone numbers can be called from Kosovo using the country codes for Serbia, Slovenia, or Morocco. These are just a few difficulties when identifying or validating phone numbers.
At first glance, it appears that one can use RegEx
to validate the country code of a phone number. However, this indicates that to validate a country’s code, we must create a unique RegEx
rule for every country worldwide.
In addition, mobile phone carriers each have guidelines (for example, certain digits can only be used in a specific range of numbers). We can see that things have the potential to quickly spiral out of control, which would make it extremely difficult for us to validate phone number inputs on our own.
Use the Phonenumbers
Library in Python
We are lucky because a Python library can effectively guide us through the validation process. This library was derived from Google’s libphonenumber
library, which can also be used for other programming languages such as C++, Java, and JavaScript.
The Python Phonenumbers
library was created using this library.
This article will show us how to use Python to validate a mobile number.
Install the Phonenumbers
Library in Python
Validating phone numbers is made easy with Python thanks to an integrated module. This module is referred to as the phonenumbers
module.
To make use of the module, we must first install it. Using pip
, we can do this:
Once the module is installed, we can validate country code phone numbers.
Now that everything has been set up, we can explore the Phonenumbers
library.
Parse Phone Numbers With Python Phonenumbers
Library
The phone number will almost certainly be a string, regardless of whether the input comes from a web form or some other source, such as text extraction (which will be covered later in this guide). It needs to be parsed with phone numbers, then converted into a PhoneNumber
instance before we can use it for validation and other purposes.
Import the Library
First, we need to import the required libraries; we will import phonenumbers
. We will also need to import the carrier
, timezone
, and geocoder
.
Example Code:
Parse the Phone Number
We can extract useful information from the phone number thanks to the parse()
method, which includes the following:
Example Code:
import phonenumbers
My_number = "+92333920000"
Parse_number = phonenumbers.parse(My_number)
A phone number string is needed as an input when using the phonenumbers.parse()
function. We can provide the national information in ISO Alpha-2 format as additional optional input.
Take into mind, for instance, the following piece of code:
Parse_number = phonenumbers.parse(My_number)
In ISO Alpha-2 notation, RO
denotes Romania. We may use this page to look up the Alpha-2 and numeric country codes for every nation worldwide.
Unless essential, the ISO Alpha-2 country code will be omitted from most instances.
Phone numbers can be validated for common issues like length, leading zeros, and signs using phonenumbers.parse()
. It’s important to remember that if any of the required conditions are not satisfied, this method will throw an exception.
Always put it in a try/catch
block in our code.
Now that our phone number has been appropriately processed, we can proceed to the validation phase.
Validate Phone Numbers Using the is_possible_number()
Method
Two approaches can be used to validate a phone number on Phonenumbers
. The primary distinction between these approaches is their respective speed and accuracy levels.
To explain this further, let’s begin with the is_possible_number()
function.
Example Code:
import phonenumbers
My_number = "+92333920000"
Parse_number = phonenumbers.parse(My_number)
print(phonenumbers.is_possible_number(Parse_number))
Output:
The program will produce a value of True
as its output.
Validate Phone Numbers Using the is_valid_number()
Method
Now, we will use the same number, but this time we’ll check its validity using the is_valid_number()
method:
Example Code:
import phonenumbers
My_number = "+92333920000"
Parse_number = phonenumbers.parse(My_number)
print(phonenumbers.is_valid_number(Parse_number))
Output:
The output would be different even though the input remained the same.
is_possible_number()
guesses the phone number’s validity by checking its length, while the is_valid_number()
method checks its length, prefix, and region.
phonenumbers.is_possible_number()
is faster than phonenumbers.is_valid_number()
in iterating over a large phone numbers list. These results aren’t always accurate, as shown.
It’s helpful to eliminate long phone numbers quickly. It’s risky to use.
Use the description_for_number()
Method in the Geocoder
Class to Find the Phone Number Location
A phone number can reveal many details about its owner, some of which may be relevant to our research. Because the particular carrier associated with a phone number is a factor in the overall cost of the product, we might want to use various application programming interfaces (APIs) or API endpoints.
We might like to send our promotion notifications based on the timezone of our customers (phone numbers) location so that we can avoid sending them a message in the middle of the night. It will prevent us from waking them up accidentally.
We could also get information about the phone number’s location to provide information pertinent to the situation. The Phonenumbers
library gives users access to the tools required to satisfy these requirements.
We will use the description_for_number()
method available in the geocoder
class to start with the location. The parameters are a phone number that has been parsed and a short name for the language.
Let’s try this with the fake number we were using before.
Example Code:
import phonenumbers
from phonenumbers import geocoder
My_number = phonenumbers.parse("+92333920000")
print("This number is from: "+geocoder.description_for_number(My_number, "en"))
Output:
This number is from: Pakistan
Use the name_for_number()
Method in the Carrier
Class to Find the Phone Number Carrier
We will use the method name_for_number()
found in the carrier
class.
Example Code:
import phonenumbers
from phonenumbers import carrier
My_number = phonenumbers.parse("+92333920000")
print("The carrier of the number is: "+carrier.name_for_number(My_number, "en"))
The output of the code:
The carrier of the number is: Ufone
Validate Phone Numbers and Get Additional Information Using Python
Example Code:
import phonenumbers
from phonenumbers import carrier, timezone, geocoder
my_number = phonenumbers.parse("+92333920000", "GB")
print((phonenumbers.is_valid_number(my_number)))
print("The carrier of the number is: "+carrier.name_for_number(my_number, "en"))
print("The content and the city of the number are:")
print(timezone.time_zones_for_number(my_number))
print("The country this number belongs to is: "+geocoder.description_for_number(my_number, 'en'))
Output:
True
The carrier of the number is: Ufone
The content and the city of the number are:
('Asia/Karachi',)
The country this number belongs to is: Pakistan
This is how we can determine whether a number is valid. We see True
in the output, which shows that the number used in the Python code is correct.
We can also find out the carrier of the number. In our case, it is Ufone
.
Along with the carrier, we can find the name of the country, continent, and city. According to the number we have used, the number is from Asia, Pakistan, and the city of Karachi.
In this tutorial, it’s shown how to find and validate phone numbers in Python using simple examples. We will review different phone number formats which are the most popular.
The best option for search and validation of data like phones numbers, zip codes, identifiers is Regular expression or Regex.
Next, we’ll see the examples to find, extract or validate phone numbers from a given text or string. The article starts with easy examples and finishes with advanced ones.
Step 1: Find Simple Phone Number
Let’s suppose that we need to validate simple phone number formats which don’t change. For example:
- 000-000-000
re.findall(r"[d]{3}-[d]{3}-[d]{3}", text)
- 000 000 0000
re.findall(r"[d]{3} [d]{3} [d]{3}", text)
The goal is to find all matches for the pattern.
The mentioned solution is very basic and it’s not working for numbers like:
9000-000-0009
— it will find only000-000-000
000 000 000
(000)000-000
In order to deal with those cases the Regex should be improved.
Step 2: Regex for Phone Numbers with a Plus
Often phones numbers are displayed with plus sign like:
- +000-000-000
This format is matched by next regular expression:
re.findall(r"+?[d]{3}-[d]{3}-[d]{3}", text)
Note that this will catch:
- 000-000-000
- +000-000-000
but also:
5000-000-0004
will be extracted as 000-000-000. In the next step we will solve this problem.
Step 3: Validate Phone Numbers for Exact Match
If the the format is important and only exact matches are needed like:
000-000-000
, +000-000-000
but not — 5000-000-0004
, +000-000-0004
then we need to add word boundaries to our Regex by adding at the start and the end b
:
re.findall(r"+?b[d]{3}-[d]{3}-[d]{3}b", text)
Next let’s see a more generic example which covers international and country phone numbers.
Step 4: Validate International Phone Number
It’s difficult to find and test international numbers with 100% accuracy. Analysis of the data might be needed in order to check what formats are present in the text.
One possible solution for validation of international numbers is:
re.match(r"^[+(]?d+(?:[- )(]+d+)+$", phone)
Another regular expression is:
re.match(r"^[+d]?(?:[d-.s()]*)$", phone)
Step 4: Validate US, UK, French phone numbers
For example let’s start with US phone numbers:
- (000)000-0000
- 000-000-0000
- (000) 000-0000
can be done with next Regex:
re.match(r"^(([0-9]{3}) ?|[0-9]{3}-)[0-9]{3}-[0-9]{4}$", phone)
UK or GB numbers like:
- +447222000000
- +44 7222 000 000
can be searched and validated by:
^(?:0|+?44)s?(?:ds?){9,11}$
other possible solution for UK is: ^(+44s?7d{3}|(?07d{3})?)s?d{3}s?d{3}(s?#(d{4}|d{3}))?$
The next simple Regex will work for French numbers:
^(?:(?:+|00)33|0)s*[d](?:[s.-]*d{2}){4}$
like:
- 00 00 00 00 00
- +33 0 00 00 00 00
Step 5: Find phone numbers in different formats
If you like to build a Regex which find various formats you can try with the next one:
[+d]?(d{2,3}[-.s]??d{2,3}[-.s]??d{4}|(d{3})s*d{3}[-.s]??d{4}|d{3}[-.s]??d{4})
The one above will cover most phone numbers but will not work for all.
If the validation is important or additional features are needed like:
- updates for new formats/countries/regions
- geographical information related to a phone number
- timezone information
then we will recommend mature libraries to be used. Good example in this case is the Google’s Java and JavaScript library for parsing, formatting, and validating international phone numbers.
Conclusion
Have in mind that Regex are powerful but you may face performance issues for the complex ones. Try to use simple and understandable Regex. Sometimes you may need to play with flags in order to make it work properly:
/^[(]?0([d{9})$/mg
Another important note is about using:
- start and end —
^
and$
- word boundaries —
b
We covered most cases of phone validation by using python and Regex.
Introduction
Validating phone numbers can be a very challenging task. The format of a phone number can vary from one country to another. Heck, it can also vary within the same country! Some countries share the same country code, while some other countries use more than one country code. According to an example from the Google’s libphonenumber
GitHub repository, USA, Canada, and Caribbean islands, all share the same country code (+1
). On the other hand, it is possible to call the phone numbers from Kosovo by Serbian, Slovenian and Moroccan country codes.
These are only a few of the challenges in identifying or validating phone numbers. At first glance, one can at least validate the country code of a phone number with a RegEx. However, this means that you would have to write a custom RegEx rule for every country in the world, just to validate a country code. On top of that, some mobile phone carriers have their own rules (for example, certain digits can only use a certain range of numbers). You can see that things can quickly get out of hand and make it almost impossible for us to validate phone number inputs by ourselves.
Luckily, there is a Python library that can help us to get through the validation process easily and efficiently. The Python Phonenumbers library is derived from Google’s libphonenumber
library, which is also available for other programming languages like C++, Java, and JavaScript.
In this tutorial, we’ll learn how to parse, validate and extract phone numbers, as well as how to extract additional information from the phone number(s) like the carrier, timezone, or geocoder details.
Using the library is very straight-forward and it’s typically used like this:
import phonenumbers
from phonenumbers import carrier, timezone, geocoder
my_number = phonenumbers.parse("+447986123456", "GB")
print(phonenumbers.is_valid_number(my_number))
print(carrier.name_for_number(my_number, "en"))
print(timezone.time_zones_for_number(my_number))
print(geocoder.description_for_number(my_number, 'en'))
And here’s the output:
True
EE
('Europe/Guernsey', 'Europe/Isle_of_Man', 'Europe/Jersey', 'Europe/London')
United Kingdom
Let’s get started by setting up our environment and installing the library.
Installing phonenumbers
First, let’s create and activate our virtual environment:
$ mkdir phonenumbers && cd phonenumbers
$ python3 -m venv venv
$ . venv/bin/active # venvScriptsactivate.bat on Windows
Then we install the Python Phonenumbers library:
$ pip3 install Phonenumbers
This tutorial will use Phonenumbers library version of 8.12.19
.
Now we are ready to start discovering the Phonenumbers library.
Parse Phone Numbers with Python phonenumbers
Whether you get user input from a web form or other sources, like extracting from some text (more on that later in this tutorial), the input phone number will most likely be a string. As a first step, we’ll need to parse it using phonenumbers
, and turn it into a PhoneNumber
instance so that we can use it for validation and other functionalities.
We can parse the phone number using the parse()
method:
import phonenumbers
my_string_number = "+40721234567"
my_number = phonenumbers.parse(my_string_number)
The phonenumbers.parse()
method takes a phone number string as a required argument. You can also pass the country information in ISO Alpha-2 format as an optional argument. Take, for example, the following code into consideration:
my_number = phonenumbers.parse(my_string_number, "RO")
«RO» stands for Romania in ISO Alpha-2 format. You can check other Alpha-2 and numeric country codes from this website. In this tutorial, for simplicity, I will omit the ISO Alpha-2 country code for most cases and include it only when it’s strictly necessary.
The phonenumbers.parse()
method already has some built-in basic validation rules like the length of a number string, or checking a leading zero, or for a +
sign. Note that this method will throw an exception when any of the needed rules are not fulfilled. So remember to use it in a try/catch block in your application.
Now that we got our phone number parsed correctly, let’s proceed to validation.
Validate Phone Numbers with Python Phonenumbers
Phonenumbers has two methods to check the validity of a phone number. The main difference between these methods is the speed and accuracy.
To elaborate, let’s start with is_possible_number()
:
import phonenumbers
my_string_number = "+40021234567"
my_number = phonenumbers.parse(my_string_number)
print(phonenumbers.is_possible_number(my_number))
And the output would be:
True
Now let’s use the same number, but with the is_valid_number()
method this time:
import phonenumbers
my_string_number = "+40021234567"
my_number = phonenumbers.parse(my_string_number)
print(phonenumbers.is_valid_number(my_number))
Even though the input was the same, the result would be different:
False
The reason is that the is_possible_number()
method makes a quick guess on the phone number’s validity by checking the length of the parsed number, while the is_valid_number()
method runs a full validation by checking the length, phone number prefix, and region.
When iterating over a large list of phone numbers, using phonenumbers.is_possible_number()
would provide faster results comparing to the phonenumbers.is_valid_number()
. But as we see here, these results may not always be accurate. It can be useful to quickly eliminate phone numbers that do not comply with the length. So use it at your own risk.
Extract and Format Phone Numbers with Python Phonenumbers
User input is not the only way to get or collect phone numbers. For instance, you may have a spider/crawler that would read certain pages from a website or a document and would extract the phone numbers from the text blocks. It sounds like a challenging problem but luckily, the Phonenumbers library provides us just the functionality we need, with the PhoneNumberMatcher(text, region)
method.
PhoneNumberMatcher
takes a text block and a region as an argument then iterates over to return the matching results as PhoneNumberMatch
objects.
Let’s use PhoneNumberMatcher
with a random text:
import phonenumbers
text_block = "Our services will cost about 2,200 USD and we will deliver the product by the 10.10.2021. For more information, you can call us at +44 7986 123456 or send an e-mail to [email protected]"
for match in phonenumbers.PhoneNumberMatcher(text_block, "GB"):
print(match)
This will print the matching phone numbers along with their index in the string:
PhoneNumberMatch [131,146) +44 7986 123456
You may have noticed that our number is formatted in the standardized international format and divided by the spaces. This may not always be the case in real-life scenarios. You may receive your number in other formats, like divided by dashes or formatted to the national (instead of the international) format.
Let’s put the PhoneNumberMatcher()
method to the test with other phone number formats:
import phonenumbers
text_block = "Our services will cost about 2,200 USD and we will deliver the product by the 10.10.2021. For more information you can call us at +44-7986-123456 or 020 8366 1177 send an e-mail to [email protected]"
for match in phonenumbers.PhoneNumberMatcher(text_block, "GB"):
print(match)
This would output:
PhoneNumberMatch [130,145) +44-7986-123456
PhoneNumberMatch [149,162) 020 8366 1177
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
Even though the phone numbers are embedded deep into the text with a variety of formats with other numbers, PhoneNumberMatcher
successfully returns the phone numbers with great accuracy.
Apart from extracting data from the text, we might also want to get the digits one by one from the user. Imagine that your app’s UI works similar to modern mobile phones, and formats the phone numbers as you type in. For instance, on your web page, you might want to pass the data to your API with each onkeyup
event and use AsYouTypeFormatter()
to format the phone number with each incoming digit.
Since UI part is out of the scope of this article, we’ll use a basic example for AsYouTypeFormatter
. To simulate on-the-fly formatting, let’s jump into the Python interpreter:
>>> import phonenumbers
>>> formatter = phonenumbers.AsYouTypeFormatter("TR")
>>> formatter.input_digit("3")
'3'
>>> formatter.input_digit("9")
'39'
>>> formatter.input_digit("2")
'392'
>>> formatter.input_digit("2")
'392 2'
>>> formatter.input_digit("2")
'392 22'
>>> formatter.input_digit("1")
'392 221'
>>> formatter.input_digit("2")
'392 221 2'
>>> formatter.input_digit("3")
'392 221 23'
>>> formatter.input_digit("4")
'392 221 23 4'
>>> formatter.input_digit("5")
'392 221 23 45'
Not all user input happens as they type. Some forms have simple text input fields for phone numbers. However, that doesn’t necessarily mean that we’ll have data entered in a standard format.
The Phonenumbers library got us covered here too with the format_number()
method. This method allows us to format phone numbers into three well-known, standardized formats. National, International, and E164. National and International formats are pretty self-explanatory, while the E164 format is an international phone number format that ensures phone numbers are limited with 15 digits and are formatted {+}{country code}{number with area code}. For more information on E164, you can check this Wikipedia page.
Let’s start with the national formatting:
import phonenumbers
my_number = phonenumbers.parse("+40721234567")
national_f = phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.NATIONAL)
print(national_f)
This will return a nicely spaced phone number string with the national format:
0721 234 567
Now let’s try to format the national number as in international format:
import phonenumbers
my_number = phonenumbers.parse("0721234567", "RO") # "RO" is ISO Alpha-2 code for Romania
international_f = phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
print(international_f)
The above code will return a nicely spaced phone number string:
+40 721 234 567
Notice that we passed "RO"
as the second parameter into the parse()
method. Since the input number is a national number, it has no country code prefix to hint at the country. In these cases, we need to specify the country with its ISO Alpha-2 code to get an accurate result. Excluding either the numeric and ISO Alpha-2 country codes, will cause an exception of NumberParseException: (0) Missing or invalid default region.
.
Now let’s try the E164
formatting option. We’ll pass a national string as the input:
import phonenumbers
my_number = phonenumbers.parse("0721234567", "RO")
e164_f=phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.E164)
print(e164_f)
The output will be very similar to the PhoneNumberFormat.INTERNATIONAL
, except with the spaces:
+40721234567
This is very useful when you want to pass the number to a background API. It isn’t uncommon for APIs to expect phone numbers to be non-spaced strings.
Get Additional Information on Phone Number
A phone number is loaded with data about a user that could be of interest to you. You may want to use different APIs or API endpoints depending on the carrier of the particular phone number since this plays a role in the product cost. You might want to send your promotion notifications depending on your customer’s (phone number’s) timezone so that you don’t send them a message in the middle of the night. Or you might want to get information about the phone number’s location so that you can provide relevant information. The Phonenumbers library provides the necessary tools to fulfill these needs.
To start with the location, we will use the description_for_number()
method from the geocoder
class. This method takes in a parsed phone number and a short language name as parameters.
Let’s try this with our previous fake number:
import phonenumbers
from phonenumbers import geocoder
my_number = phonenumbers.parse("+447986123456")
print(geocoder.description_for_number(my_number, "en"))
This will print out the origin country of the phone number:
United Kingdom
Short language names are pretty intuitive. Let’s try to get output in Russian:
import phonenumbers
from phonenumbers import geocoder
my_number = phonenumbers.parse("+447986123456")
print(geocoder.description_for_number(my_number, "ru"))
And here’s the output which says the United Kingdom in Russian:
Соединенное Королевство
You can try it out with other languages of your preferences like «de», «fr», «zh», etc.
As mentioned before, you might want to group your phone numbers by their carriers, since in most cases it will have an impact on the cost. To clarify, the Phonenumbers library probably will provide most of the carrier names accurately, but not 100%.
Today in most countries it is possible to get your number from one carrier and later on move the same number to a different carrier, leaving the phone number exactly the same. Since Phonenumbers is merely an offline Python library, it is not possible to detect these changes. So it’s best to approach the carrier names as a reference, rather than a fact.
We will use the name_for_number()
method from carrier
class:
import phonenumbers
from phonenumbers import carrier
my_number = phonenumbers.parse("+40721234567")
print(carrier.name_for_number(my_number, "en"))
This will display the original carrier of the phone number if possible:
Vodafone
Note: As it is mentioned in the original documents of the Python Phonenumbers, carrier information is available for mobile numbers in some countries, not all.
Another important piece of information about a phone number is its timezone. The time_zones_for_number()
method will return a list of timezones that the number belongs to. We’ll import it from phonenumbers.timezone
:
import phonenumbers
from phonenumbers import timezone
my_number = phonenumbers.parse("+447986123456")
print(timezone.time_zones_for_number(my_number))
This will print the following timezones:
('Europe/Guernsey', 'Europe/Isle_of_Man', 'Europe/Jersey', 'Europe/London')
This concludes our tutorial on Python Phonenumbers.
Conclusion
We learned how to parse phone numbers with parse()
method, extract numbers from text blocks with PhoneNumberMatcher()
, get the phone numbers digit by digit and format it with AsYouTypeFormatter()
, use different validation methods with is_possible_number()
and is_possible_number()
, format numbers using NATIONAL
, INTERNATIONAL
, and E164
formatting methods, and extract additional information from the phone numbers using geocoder
, carrier
, and timezone
classes.
Remember to check out the original GitHub repo of the Phonenumbers library. Also if you have any questions in mind, feel free to comment below.
phonenumbers Python Library
This is a Python port of Google’s libphonenumber library
It supports Python 2.5-2.7 and Python 3.x (in the same codebase, with no
2to3 conversion needed).
Original Java code is Copyright (C) 2009-2015 The Libphonenumber Authors.
Release HISTORY,
derived from upstream release notes.
Installation
Install using pip with:
pip install phonenumbers
Example Usage
The main object that the library deals with is a PhoneNumber
object. You can create this from a string
representing a phone number using the parse
function, but you also need to specify the country
that the phone number is being dialled from (unless the number is in E.164 format, which is globally
unique).
>>> import phonenumbers >>> x = phonenumbers.parse("+442083661177", None) >>> print(x) Country Code: 44 National Number: 2083661177 Leading Zero: False >>> type(x) <class 'phonenumbers.phonenumber.PhoneNumber'> >>> y = phonenumbers.parse("020 8366 1177", "GB") >>> print(y) Country Code: 44 National Number: 2083661177 Leading Zero: False >>> x == y True >>> z = phonenumbers.parse("00 1 650 253 2222", "GB") # as dialled from GB, not a GB number >>> print(z) Country Code: 1 National Number: 6502532222 Leading Zero(s): False
The PhoneNumber
object that parse
produces typically still needs to be validated, to check whether
it’s a possible number (e.g. it has the right number of digits) or a valid number (e.g. it’s
in an assigned exchange).
>>> z = phonenumbers.parse("+120012301", None) >>> print(z) Country Code: 1 National Number: 20012301 Leading Zero: False >>> phonenumbers.is_possible_number(z) # too few digits for USA False >>> phonenumbers.is_valid_number(z) False >>> z = phonenumbers.parse("+12001230101", None) >>> print(z) Country Code: 1 National Number: 2001230101 Leading Zero: False >>> phonenumbers.is_possible_number(z) True >>> phonenumbers.is_valid_number(z) # NPA 200 not used False
The parse
function will also fail completely (with a NumberParseException
) on inputs that cannot
be uniquely parsed, or that can’t possibly be phone numbers.
>>> z = phonenumbers.parse("02081234567", None) # no region, no + => unparseable Traceback (most recent call last): File "phonenumbers/phonenumberutil.py", line 2350, in parse "Missing or invalid default region.") phonenumbers.phonenumberutil.NumberParseException: (0) Missing or invalid default region. >>> z = phonenumbers.parse("gibberish", None) Traceback (most recent call last): File "phonenumbers/phonenumberutil.py", line 2344, in parse "The string supplied did not seem to be a phone number.") phonenumbers.phonenumberutil.NumberParseException: (1) The string supplied did not seem to be a phone number.
Once you’ve got a phone number, a common task is to format it in a standardized format. There are a few
formats available (under PhoneNumberFormat
), and the format_number
function does the formatting.
>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.NATIONAL) '020 8366 1177' >>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.INTERNATIONAL) '+44 20 8366 1177' >>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.E164) '+442083661177'
If your application has a UI that allows the user to type in a phone number, it’s nice to get the formatting
applied as the user types. The AsYouTypeFormatter
object allows this.
>>> formatter = phonenumbers.AsYouTypeFormatter("US") >>> formatter.input_digit("6") '6' >>> formatter.input_digit("5") '65' >>> formatter.input_digit("0") '650' >>> formatter.input_digit("2") '650 2' >>> formatter.input_digit("5") '650 25' >>> formatter.input_digit("3") '650 253' >>> formatter.input_digit("2") '650-2532' >>> formatter.input_digit("2") '(650) 253-22' >>> formatter.input_digit("2") '(650) 253-222' >>> formatter.input_digit("2") '(650) 253-2222'
Sometimes, you’ve got a larger block of text that may or may not have some phone numbers inside it. For this,
the PhoneNumberMatcher
object provides the relevant functionality; you can iterate over it to retrieve a
sequence of PhoneNumberMatch
objects. Each of these match objects holds a PhoneNumber
object together
with information about where the match occurred in the original string.
>>> text = "Call me at 510-748-8230 if it's before 9:30, or on 703-4800500 after 10am." >>> for match in phonenumbers.PhoneNumberMatcher(text, "US"): ... print(match) ... PhoneNumberMatch [11,23) 510-748-8230 PhoneNumberMatch [51,62) 703-4800500 >>> for match in phonenumbers.PhoneNumberMatcher(text, "US"): ... print(phonenumbers.format_number(match.number, phonenumbers.PhoneNumberFormat.E164)) ... +15107488230 +17034800500
You might want to get some information about the location that corresponds to a phone number. The
geocoder.area_description_for_number
does this, when possible.
>>> from phonenumbers import geocoder >>> ch_number = phonenumbers.parse("0431234567", "CH") >>> geocoder.description_for_number(ch_number, "de") 'Zürich' >>> geocoder.description_for_number(ch_number, "en") 'Zurich' >>> geocoder.description_for_number(ch_number, "fr") 'Zurich' >>> geocoder.description_for_number(ch_number, "it") 'Zurigo'
For mobile numbers in some countries, you can also find out information about which carrier
originally owned a phone number.
>>> from phonenumbers import carrier >>> ro_number = phonenumbers.parse("+40721234567", "RO") >>> carrier.name_for_number(ro_number, "en") 'Vodafone'
You might also be able to retrieve a list of time zone names that the number potentially
belongs to.
>>> from phonenumbers import timezone >>> gb_number = phonenumbers.parse("+447986123456", "GB") >>> timezone.time_zones_for_number(gb_number) ('Atlantic/Reykjavik', 'Europe/London')
For more information about the other functionality available from the library, look in the unit tests or in the original
libphonenumber project.
Memory Usage
The library includes a lot of metadata, potentially giving a significant memory overhead. There are two mechanisms
for dealing with this.
- The normal metadata (just over 2 MiB of generated Python code) for the core functionality of the library is loaded
on-demand, on a region-by-region basis (i.e. the metadata for a region is only loaded on the first time it is needed). - Metadata for extended functionality is held in separate packages, which therefore need to be explicitly
loaded separately. This affects:- The geocoding metadata (~19 MiB), which is held in
phonenumbers.geocoder
and used by the geocoding functions
(geocoder.description_for_number
,geocoder.description_for_valid_number
or
geocoder.country_name_for_number
). - The carrier metadata (~1 MiB), which is held in
phonenumbers.carrier
and used by the mapping functions
(carrier.name_for_number
orcarrier.name_for_valid_number
). - The timezone metadata (~100 KiB), which is held in
phonenumbers.timezone
and used by the timezone functions
(time_zones_for_number
ortime_zones_for_geographical_number
).
- The geocoding metadata (~19 MiB), which is held in
The phonenumberslite
version of the library does not include the geocoder, carrier and timezone packages,
which can be useful if you have problems installing the main phonenumbers
library due to space/memory limitations.
If you need to ensure that the metadata memory use is accounted for at start of day (i.e. that a subsequent on-demand
load of metadata will not cause a pause or memory exhaustion):
- Force-load the normal metadata by calling
phonenumbers.PhoneMetadata.load_all()
. - Force-load the extended metadata by
import
ing the appropriate packages (phonenumbers.geocoder
,
phonenumbers.carrier
,phonenumbers.timezone
).
The phonenumberslite
version of the package does not include the geocoding, carrier and timezone metadata,
which can be useful if you have problems installing the main phonenumbers
package due to space/memory limitations.
Static Typing
The library includes a set of type stub files to support static
type checking by library users. These stub files signal the types that should be used, and may also be of use in IDEs
which have integrated type checking functionalities.
These files are written for Python 3, and as such type checking the library with these stubs on Python 2.5-2.7 is
unsupported.
Project Layout
- The
python/
directory holds the Python code. - The
resources/
directory is a copy of theresources/
directory from
libphonenumber.
This is not needed to run the Python code, but is needed when upstream
changes to the master metadata need to be incorporated. - The
tools/
directory holds the tools that are used to process upstream
changes to the master metadata.
phonenumbers Python Library
This is a Python port of Google’s libphonenumber library
It supports Python 2.5-2.7 and Python 3.x (in the same codebase, with no
2to3 conversion needed).
Original Java code is Copyright (C) 2009-2015 The Libphonenumber Authors.
Release HISTORY,
derived from upstream release notes.
Installation
Install using pip with:
Example Usage
The main object that the library deals with is a PhoneNumber
object. You can create this from a string
representing a phone number using the parse
function, but you also need to specify the country
that the phone number is being dialled from (unless the number is in E.164 format, which is globally
unique).
>>> import phonenumbers >>> x = phonenumbers.parse("+442083661177", None) >>> print(x) Country Code: 44 National Number: 2083661177 Leading Zero: False >>> type(x) <class 'phonenumbers.phonenumber.PhoneNumber'> >>> y = phonenumbers.parse("020 8366 1177", "GB") >>> print(y) Country Code: 44 National Number: 2083661177 Leading Zero: False >>> x == y True >>> z = phonenumbers.parse("00 1 650 253 2222", "GB") # as dialled from GB, not a GB number >>> print(z) Country Code: 1 National Number: 6502532222 Leading Zero(s): False
The PhoneNumber
object that parse
produces typically still needs to be validated, to check whether
it’s a possible number (e.g. it has the right number of digits) or a valid number (e.g. it’s
in an assigned exchange).
>>> z = phonenumbers.parse("+120012301", None) >>> print(z) Country Code: 1 National Number: 20012301 Leading Zero: False >>> phonenumbers.is_possible_number(z) # too few digits for USA False >>> phonenumbers.is_valid_number(z) False >>> z = phonenumbers.parse("+12001230101", None) >>> print(z) Country Code: 1 National Number: 2001230101 Leading Zero: False >>> phonenumbers.is_possible_number(z) True >>> phonenumbers.is_valid_number(z) # NPA 200 not used False
The parse
function will also fail completely (with a NumberParseException
) on inputs that cannot
be uniquely parsed, or that can’t possibly be phone numbers.
>>> z = phonenumbers.parse("02081234567", None) # no region, no + => unparseable Traceback (most recent call last): File "phonenumbers/phonenumberutil.py", line 2350, in parse "Missing or invalid default region.") phonenumbers.phonenumberutil.NumberParseException: (0) Missing or invalid default region. >>> z = phonenumbers.parse("gibberish", None) Traceback (most recent call last): File "phonenumbers/phonenumberutil.py", line 2344, in parse "The string supplied did not seem to be a phone number.") phonenumbers.phonenumberutil.NumberParseException: (1) The string supplied did not seem to be a phone number.
Once you’ve got a phone number, a common task is to format it in a standardized format. There are a few
formats available (under PhoneNumberFormat
), and the format_number
function does the formatting.
>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.NATIONAL) '020 8366 1177' >>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.INTERNATIONAL) '+44 20 8366 1177' >>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.E164) '+442083661177'
If your application has a UI that allows the user to type in a phone number, it’s nice to get the formatting
applied as the user types. The AsYouTypeFormatter
object allows this.
>>> formatter = phonenumbers.AsYouTypeFormatter("US") >>> formatter.input_digit("6") '6' >>> formatter.input_digit("5") '65' >>> formatter.input_digit("0") '650' >>> formatter.input_digit("2") '650 2' >>> formatter.input_digit("5") '650 25' >>> formatter.input_digit("3") '650 253' >>> formatter.input_digit("2") '650-2532' >>> formatter.input_digit("2") '(650) 253-22' >>> formatter.input_digit("2") '(650) 253-222' >>> formatter.input_digit("2") '(650) 253-2222'
Sometimes, you’ve got a larger block of text that may or may not have some phone numbers inside it. For this,
the PhoneNumberMatcher
object provides the relevant functionality; you can iterate over it to retrieve a
sequence of PhoneNumberMatch
objects. Each of these match objects holds a PhoneNumber
object together
with information about where the match occurred in the original string.
>>> text = "Call me at 510-748-8230 if it's before 9:30, or on 703-4800500 after 10am." >>> for match in phonenumbers.PhoneNumberMatcher(text, "US"): ... print(match) ... PhoneNumberMatch [11,23) 510-748-8230 PhoneNumberMatch [51,62) 703-4800500 >>> for match in phonenumbers.PhoneNumberMatcher(text, "US"): ... print(phonenumbers.format_number(match.number, phonenumbers.PhoneNumberFormat.E164)) ... +15107488230 +17034800500
You might want to get some information about the location that corresponds to a phone number. The
geocoder.area_description_for_number
does this, when possible.
>>> from phonenumbers import geocoder >>> ch_number = phonenumbers.parse("0431234567", "CH") >>> geocoder.description_for_number(ch_number, "de") 'Zürich' >>> geocoder.description_for_number(ch_number, "en") 'Zurich' >>> geocoder.description_for_number(ch_number, "fr") 'Zurich' >>> geocoder.description_for_number(ch_number, "it") 'Zurigo'
For mobile numbers in some countries, you can also find out information about which carrier
originally owned a phone number.
>>> from phonenumbers import carrier >>> ro_number = phonenumbers.parse("+40721234567", "RO") >>> carrier.name_for_number(ro_number, "en") 'Vodafone'
You might also be able to retrieve a list of time zone names that the number potentially
belongs to.
>>> from phonenumbers import timezone >>> gb_number = phonenumbers.parse("+447986123456", "GB") >>> timezone.time_zones_for_number(gb_number) ('Atlantic/Reykjavik', 'Europe/London')
For more information about the other functionality available from the library, look in the unit tests or in the original
libphonenumber project.
Memory Usage
The library includes a lot of metadata, potentially giving a significant memory overhead. There are two mechanisms
for dealing with this.
- The normal metadata (just over 2 MiB of generated Python code) for the core functionality of the library is loaded
on-demand, on a region-by-region basis (i.e. the metadata for a region is only loaded on the first time it is needed). - Metadata for extended functionality is held in separate packages, which therefore need to be explicitly
loaded separately. This affects:- The geocoding metadata (~19 MiB), which is held in
phonenumbers.geocoder
and used by the geocoding functions
(geocoder.description_for_number
,geocoder.description_for_valid_number
or
geocoder.country_name_for_number
). - The carrier metadata (~1 MiB), which is held in
phonenumbers.carrier
and used by the mapping functions
(carrier.name_for_number
orcarrier.name_for_valid_number
). - The timezone metadata (~100 KiB), which is held in
phonenumbers.timezone
and used by the timezone functions
(time_zones_for_number
ortime_zones_for_geographical_number
).
- The geocoding metadata (~19 MiB), which is held in
The phonenumberslite
version of the library does not include the geocoder, carrier and timezone packages,
which can be useful if you have problems installing the main phonenumbers
library due to space/memory limitations.
If you need to ensure that the metadata memory use is accounted for at start of day (i.e. that a subsequent on-demand
load of metadata will not cause a pause or memory exhaustion):
- Force-load the normal metadata by calling
phonenumbers.PhoneMetadata.load_all()
. - Force-load the extended metadata by
import
ing the appropriate packages (phonenumbers.geocoder
,
phonenumbers.carrier
,phonenumbers.timezone
).
The phonenumberslite
version of the package does not include the geocoding, carrier and timezone metadata,
which can be useful if you have problems installing the main phonenumbers
package due to space/memory limitations.
Static Typing
The library includes a set of type stub files to support static
type checking by library users. These stub files signal the types that should be used, and may also be of use in IDEs
which have integrated type checking functionalities.
These files are written for Python 3, and as such type checking the library with these stubs on Python 2.5-2.7 is
unsupported.
Project Layout
- The
python/
directory holds the Python code. - The
resources/
directory is a copy of theresources/
directory from
libphonenumber.
This is not needed to run the Python code, but is needed when upstream
changes to the master metadata need to be incorporated. - The
tools/
directory holds the tools that are used to process upstream
changes to the master metadata.