Where is this IP address located?
Sometimes you need the geolocation of an IP-address, for example to gather insights on visitors of a website. But how do you do it?
I recently ran onto a case where I needed the (lat,lon) coordinates for visiting IP addresses. It sounded like a simple question but required multiple steps to fulfill:
- A DNS lookup for a hostname
- The geolocation of an IP address
- The lat,lon coordinates for the geolocation (geocoding)
For these steps, we will use the following tools:
- built-in python socket module
- IPAPI geolocation API
- OpenCage Geocoding API (optional, depending on the geolocation API)
So the first step is to translate a hostname to an IP address using socket.gethostbyname
. The advantage of this function is that if an IP address is given as parameter, it returns the IP address itself.
import socket
hostname = 'www.google.com'def get_ip(hostname):
return socket.gethostbyname('google.com')
After calling this function it is guaranteed that an IP address is available. The next step is to convert the IP address to a geolocation. In this example IPAPI is used but there are multiple API providers for geolocation available, like IPStack and IP GEO API.
import requestsdef get_location(hostname):
ip = get_ip(hostname)
url = 'https://ipapi.co/{}/json/'.format(ip)
response = requests.get(url).json()
return {
"city": response.get("city"),
"country": response.get("country_name"),
"latitude": response.get("latitude"),
"longitude": response.get("longitude")
}
This will return the geolocation of an IP address:
get_location('142.250.179.174'){
'city': 'Helsinki',
'country': 'Finland',
'latitude': 60.1719,
'longitude': 24.9347
}
The IPAPI can return the geolocation in different formats, like JSON and CSV. Using the JSON option makes it easy to convert it to a dictionary with the geolocation. The API returns more information, but for this purpose this is all we need. The full response is:
{
'ip': '142.250.179.174',
'version': 'IPv4',
'city': 'Helsinki',
'region': 'Uusimaa',
'region_code': '18',
'country': 'FI',
'country_name': 'Finland',
'country_code': 'FI',
'country_code_iso3': 'FIN',
'country_capital': 'Helsinki',
'country_tld': '.fi',
'continent_code': 'EU',
'in_eu': True,
'postal': '00131',
'latitude': 60.1719,
'longitude': 24.9347,
'timezone': 'Europe/Helsinki',
'utc_offset': '+0200',
'country_calling_code': '+358',
'currency': 'EUR',
'currency_name': 'Euro',
'languages': 'fi-FI,sv-FI,smn',
'country_area': 337030.0,
'country_population': 5518050,
'asn': 'AS15169',
'org': 'GOOGLE'
}
So with IPAPI all our requirements are fulfilled and we have the city and country name for the IP address and the (lat, lon) location.
In case the (lat, lon) location is not part of the data a geolocation service like OpenCage can be used to translate the city/country to the (lat, lon) coordinates:
import requestsAPI_KEY = <YOUR_APIKEY_HERE>def get_lat_lon(location):
loc = '{}, {}'.format(location['city'],
location['country'])
url = 'https://api.opencagedata.com/geocode/v1/json?' \
'q={}&key={}'.format(loc, API_KEY)
result = requests.get(url).json() if result['total_results'] > 0:
geo = result['results'][0]['geometry'] return {
"latitude": geo.get("lat"),
"longitude": geo.get("lng"),
} else:
return None
An API key for OpenCage can be obtained here. OpenCage supports both forward and reverse geocoding. Details on using his API can be found here. A list op geocoded locations is returned upon request and we used the first result here.
location = get_location('www.google.com')geolocation = get_lat_lon(location)
print(geolocation)
{
'latitude': 60.1674881,
'longitude': 24.9427473
}
Is it accurate? No. Geocoding IP addresses gives the location of the owner of an IP address. In my personal case, it is my Internet Service Provider (ISP). Finding the location of my personal IP address results in the location of my ISP, at the other side of the country, about 100 kilometres away. For some use cases this might be sufficient, e.g. finding the origin country of website visitors, or a rough indication of the regions where visitors are coming from.
I hope you enjoyed this article. For more inspiration check some of my other articles:
- Perform a function on columns in a CSV file
- Create a heatmap from the logs of your activity tracker
- Remove personal information from text with Python
- Parallel web requests with Python
- All public transport leads to Utrecht, not Rome
Disclaimer: The views and opinions included in this article belong only to the author.