Skip to content

Commit be23b99

Browse files
committed
add phone number tracker tutorial
1 parent 4783b9b commit be23b99

File tree

4 files changed

+155
-0
lines changed

4 files changed

+155
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
4141
- [How to Perform DNS Enumeration in Python](https://www.thepythoncode.com/article/dns-enumeration-with-python). ([code](ethical-hacking/dns-enumeration))
4242
- [How to Geolocate IP addresses in Python](https://www.thepythoncode.com/article/geolocate-ip-addresses-with-ipinfo-in-python). ([code](ethical-hacking/geolocating-ip-addresses))
4343
- [How to Crack Hashes in Python](https://thepythoncode.com/article/crack-hashes-in-python). ([code](ethical-hacking/hash-cracker))
44+
- [How to Make a Phone Number Tracker in Python](https://thepythoncode.com/article/phone-number-tracker-in-python). ([code](ethical-hacking/phone-number-tracker))
4445

4546
- ### [Machine Learning](https://www.thepythoncode.com/topic/machine-learning)
4647
- ### [Natural Language Processing](https://www.thepythoncode.com/topic/nlp)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# [How to Make a Phone Number Tracker in Python](https://thepythoncode.com/article/phone-number-tracker-in-python)
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import phonenumbers, sys, folium, os, argparse
2+
from colorama import init, Fore
3+
from phonenumbers import geocoder, timezone, carrier
4+
init()
5+
6+
7+
def process_number(number):
8+
try:
9+
global location
10+
11+
# Parse the phone number. See this as extracting relevant information from the Phone number.
12+
parsed_number = phonenumbers.parse(number)
13+
14+
'''Display a message indicating the tracking attempt. We'll also format the parsed number to the
15+
international format.'''
16+
17+
print(f"{Fore.GREEN}[+] Attempting to track location of "
18+
f"{phonenumbers.format_number(parsed_number, phonenumbers.PhoneNumberFormat.INTERNATIONAL)}..")
19+
20+
# Get and display the time zone ID
21+
print(f"{Fore.GREEN}[+] Time Zone ID: {timezone.time_zones_for_number(parsed_number)}")
22+
23+
# Get the geographic location of the Phone number and display it.
24+
location = geocoder.description_for_number(parsed_number, "en")
25+
if location:
26+
print(f"{Fore.GREEN}[+] Region: {location}")
27+
else:
28+
print(f"{Fore.RED}[-] Region: Unknown")
29+
30+
'''Get the service provider (carrier) and display it if available. Some businesses and
31+
organizations do not use public service providers. So you may not see the carrier in that case.'''
32+
33+
if carrier.name_for_number(parsed_number, 'en'):
34+
print(f"{Fore.GREEN}[+] Service Provider: {carrier.name_for_number(parsed_number, 'en')}")
35+
else:
36+
pass
37+
38+
# Handle exceptions, such as invalid phone numbers or connectivity issues.
39+
except Exception:
40+
print(f"{Fore.RED}[-] Please specify a valid phone number (with country code)"
41+
" or check your internet connection.")
42+
sys.exit()
43+
44+
def get_approx_coordinates():
45+
# Import the OpenCageGeocode class from the opencage.geocoder module
46+
from opencage.geocoder import OpenCageGeocode
47+
48+
global coder, latitude, longitude
49+
50+
# Try to execute the following block, and handle exceptions if they occur.
51+
try:
52+
# Create an instance of the OpenCageGeocode class with your API key.
53+
coder = OpenCageGeocode("42c84373c47e490ba410d4132ae64fc4")
54+
55+
query = location
56+
57+
# Perform a geocoding query to obtain results.
58+
results = coder.geocode(query)
59+
60+
# Extract latitude and longitude from the geocoding results. These are the coordinates of the number's location.
61+
latitude = results[0]['geometry']['lat']
62+
longitude = results[0]['geometry']['lng']
63+
64+
# Print the obtained latitude and longitude.
65+
print(f"[+] Latitude: {latitude}, Longitude: {longitude}")
66+
67+
# Perform a reverse geocoding query to obtain an address based on coordinates.
68+
address = coder.reverse_geocode(latitude, longitude)
69+
70+
# Check if an address was found.
71+
if address:
72+
address = address[0]['formatted']
73+
print(f"{Fore.LIGHTRED_EX}[+] Approximate Location is {address}")
74+
else:
75+
# If no address was found, print an error message.
76+
print(f"{Fore.RED}[-] No address found for the given coordinates.")
77+
except Exception:
78+
'''Handle exceptions by printing an error message and exiting the script. This would prevent the program from
79+
crashing'''
80+
81+
print(f"{Fore.RED}[-] Could not get the location of this number. Please specify a valid phone number or "
82+
"check your internet connection.")
83+
sys.exit()
84+
85+
# This function basically removes unwanted characters from the Phone number such as white spaces.
86+
def clean_phone_number(phone_number):
87+
cleaned = ''.join(char for part in phone_number for char in part if char.isdigit() or char == '+')
88+
return cleaned or "unknown"
89+
90+
# Function to see Aerial view of the person's location.
91+
def draw_map():
92+
try:
93+
# Create a Folium map centered around the latitude and longitude of the number's coordinates.
94+
my_map = folium.Map(location=[latitude, longitude], zoom_start=9)
95+
96+
# Add a marker to the map at the specified latitude and longitude with a popup displaying the 'location' variable.
97+
folium.Marker([latitude, longitude], popup=location).add_to(my_map)
98+
99+
''' Clean the phone number and use it to generate a file name with an '.html' extension
100+
we'll basically save each map with the number of the owner for easy identification.'''
101+
102+
cleaned_phone_number = clean_phone_number(args.phone_number) # We'll see 'args' soon.
103+
file_name = f"{cleaned_phone_number}.html"
104+
105+
# Save the map as an HTML file with the generated file name.
106+
my_map.save(file_name)
107+
108+
# Print a message indicating where the saved HTML file can be found.
109+
print(f"[+] See Aerial Coverage at: {os.path.abspath(file_name)}")
110+
111+
# Handle the 'NameError' exception, which can occur if the 'latitude' or 'longitude' variables are not defined.
112+
except NameError:
113+
print(f"{Fore.RED}[-] Could not get Aerial coverage for this number. Please check the number again.")
114+
115+
116+
# Function to handle command-line arguments.
117+
def cli_argument():
118+
# Create an ArgumentParser object and specify a description.
119+
parser = argparse.ArgumentParser(description="Get approximate location of a Phone number.")
120+
121+
# Define a command-line argument: -p or --phone. This is to receive the user's number from terminal.
122+
parser.add_argument("-p", "--phone", dest="phone_number", type=str,
123+
help="Phone number to track. Please include the country code when specifying the number.",
124+
required=True, nargs="+")
125+
126+
# Parse the command-line arguments.
127+
argument = parser.parse_args()
128+
129+
# Check if the 'phone_number' argument is not provided.
130+
if not argument.phone_number:
131+
# Print an error message indicating that the phone number is required.
132+
print(f"{Fore.RED}[-] Please specify the phone number to track (including country code)."
133+
" Use --help to see usage.")
134+
135+
# Exit the script.
136+
sys.exit()
137+
138+
# Return the parsed command-line arguments.
139+
return argument
140+
141+
# Parse command-line arguments using the 'cli_argument' function.
142+
args = cli_argument()
143+
144+
# Call the process_number function and pass the phone number as a single string.
145+
process_number("".join(args.phone_number))
146+
get_approx_coordinates()
147+
draw_map()
148+
149+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
phonenumbers
2+
folium
3+
colorama
4+
opencage

0 commit comments

Comments
 (0)