61

I am developing a project, that needs to store user location in my data base. I got the public IP address of that user. But I am unable to get the user location. I have tried several ways (from StackOverflow) but I didn't find any hint. Like the below

url = urllib.urlopen("http://api.hostip.info/get_html.php?ip=%s&position=true" % ip)
data = re.compile('^[^\(]+\(|\)$').sub('', url.read())
print data

but I am getting the result as

Unknown Country?) (XX)
City: (Unknown City?)

another way:

import urllib

response = urllib.urlopen("http://api.hostip.info/get_html.php?ip={}&position=true".format(ip)).read()

print(response)

but the result is

Country: (Unknown Country?) (XX)
City: (Unknown City?)

Latitude: 
Longitude: 
IP: 115.xxx.xxx.xx

Any help would be appreciated!

3
  • obviously hostip.info does not know what country that IP belongs to. Commented Jul 10, 2014 at 13:53
  • @AnttiHaapala, i tried with ipinfodb.com also, but for two different ip locations it is giving the same address Commented Jul 10, 2014 at 13:55
  • Before trying to regex extract relevant parts, what gives print url.read() ? Commented Jul 10, 2014 at 14:13

14 Answers 14

48

One of the simplest methods for getting the IP address as well as the location in detail is to use http://ipinfo.io

import re
import json
from urllib2 import urlopen

url = 'http://ipinfo.io/json'
response = urlopen(url)
data = json.load(response)

IP=data['ip']
org=data['org']
city = data['city']
country=data['country']
region=data['region']

print 'Your IP detail\n '
print 'IP : {4} \nRegion : {1} \nCountry : {2} \nCity : {3} \nOrg : {0}'.format(org,region,country,city,IP)
Sign up to request clarification or add additional context in comments.

2 Comments

Isn't this paid service?
As it turns out, they made their own Python library! github.com/ipinfo/python a.k.a. pip install ipinfo
24

for python-3.x

def print_ip_info(addr=None):
    from urllib.request import urlopen
    import json
    if addr is None:
        url = 'https://ipinfo.io/json'
    else:
        url = 'https://ipinfo.io/' + addr + '/json'
    # if res==None, check your internet connection
    res = urlopen(url)
    data = json.load(res)
    for attr in data.keys():
        # print the data line by line
        print(attr, ' '*13 + '\t->\t', data[attr])

1 Comment

Works like a charm Python 3.6 64bit
23

Thanks for all the solutions and workarounds! However, I was not able to use all of the above methods.

Here is what worked for me:

import requests

response = requests.get("https://geolocation-db.com/json/39.110.142.79&position=true").json()

This method seemed simple and easy to use. (I needed to work with a dictionary response...)

In the future, the "geolocation-db.com" might become unavailable, so alternative sources might be required!

Comments

19

Try with pygeoip (It looks deprecated)

~$ ping stackoverflow.com
PING stackoverflow.com (198.252.206.16) 56(84) bytes of data.

>>> import pygeoip
>>> GEOIP = pygeoip.GeoIP("/absolute_path/GeoIP.dat", pygeoip.MEMORY_CACHE)
>>> GEOIP.country_name_by_addr(ip)
'United States'

GeoIP.data is available here

2 Comments

It looks deprecated.
i has been deprecated for github.com/maxmind/GeoIP2-python
12

You can use the services of https://geolocation-db.com IPv4 and IPv6 are supported. Either a JSON-object or JSONP callback function is returned.

Python 2:

import urllib
import json

url = "https://geolocation-db.com/json"
response = urllib.urlopen(url)
data = json.loads(response.read())
print data

Python 3:

import urllib.request
import json

with urllib.request.urlopen("https://geolocation-db.com/json") as url:
    data = json.loads(url.read().decode())
    print(data)

A python 3 jsonp example:

import urllib.request
import json

with urllib.request.urlopen("https://geolocation-db.com/jsonp/8.8.8.8") as url:
    data = url.read().decode()
    data = data.split("(")[1].strip(")")
    print(data)

3 Comments

Doesn't look like https://geoip-db.com/json/{other IP} is supported; all queries return the IP of the machine running the script.
Indeed correct for json. The https://geoip-db.com/jsonp/ callback however works.
It works well but is very slow.
11

Assuming that you got the ip address already, you can try to use the IP2Location Python Library to get the user location. A sample code is like this:

import os
import IP2Location

database = IP2Location.IP2Location(os.path.join("data", "IPV4-COUNTRY.BIN"))

rec = database.get_all(ip)

print(rec.country_short)
print(rec.country_long)
print(rec.region)
print(rec.city)
print(rec.isp)  
print(rec.latitude)
print(rec.longitude)            
print(rec.domain)
print(rec.zipcode)
print(rec.timezone)
print(rec.netspeed)
print(rec.idd_code)
print(rec.area_code)
print(rec.weather_code)
print(rec.weather_name)
print(rec.mcc)
print(rec.mnc)
print(rec.mobile_brand)
print(rec.elevation)
print(rec.usage_type)

Depends on your requirement, for example if you want to get the user's country name and region name, you can do this:

import os
import IP2Location

database = IP2Location.IP2Location(os.path.join("data", "IPV4-COUNTRY.BIN"))

rec = database.get_all(ip)

user_country = rec.country_long
user_region = rec.region

For more details, you can visit here: IP2Location Python library

Github link: IP2Location Python library Github

2 Comments

Great offline solution.
Excellent method with high speed. Use as the first method and then use other solutions as the second methods.
6

I found ipinfo offering the best service and providing free API usage for up to 50k calls per month - see 'Rate Limits' here:

import ipinfo

access_token = '123456789abc'
handler = ipinfo.getHandler(access_token)
ip_address = '216.239.36.21'
details = handler.getDetails(ip_address)
details.city
'Mountain View'
details.country
'US'
details.loc
'37.3861,-122.0840'

Comments

4

requirements:

sudo add-apt-repository ppa:maxmind/ppa
sudo apt update
sudo apt install libmaxminddb0 libmaxminddb-dev mmdb-bin
sudo pip install geoip2

geoip database:

wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz
tar xvfz GeoLite2-City.tar.gz

example for nginx access logs:

python -c 'import geoip2.database
reader = geoip2.database.Reader("./GeoLite2-City/GeoLite2-City.mmdb")
for line in open("/var/log/nginx/access.log').readlines():
    response = reader.city(line.split(" ")[0])
    print(dir(response))
'

related:

1 Comment

For me 'pip install geoip2' worked. No need to add maxmin repo and apt-install libraries. (debian-testing February 2019)
3

I'm doing this same thing on own server. Get an API key from http://ipinfodb.com/register.php and try:

import requests

ipdb = "http://api.ipinfodb.com/v3/ip-city/?key=<your api key>&ip="
ip_address = function_to_get_ip_address()
location = " ".join(str(requests.get(ipdb+ip_address).text).split(";")[4:7])

The value of location will be COUNTRY REGION CITY.

Keep in mind that IP addresses are not precise geo-locators. Especially when accessing your website from a mobile device, you'll see that the location of the IP address to be maybe 100 miles away from the physical location of the user.

Comments

3

It ultimately depends on how you get your computers IP address. If you are on a VPN or another private network, just getting the local IP address will return nothing, like you are seeing now. In this case you have to get the public IP address like so:

url = 'http://api.hostip.info/get_json.php'
info = json.loads(urllib.urlopen(url).read())
ip = info['ip']

Here is my full code for getting all the information that you are seeking (I used freegeoip.net):

import urllib
import json

url = 'http://api.hostip.info/get_json.php'
info = json.loads(urllib.urlopen(url).read())
ip = info['ip']

urlFoLaction = "http://www.freegeoip.net/json/{0}".format(ip)
locationInfo = json.loads(urllib.urlopen(urlFoLaction).read())
print 'Country: ' + locationInfo['country_name']
print 'City: ' + locationInfo['city']
print ''
print 'Latitude: ' + str(locationInfo['latitude'])
print 'Longitude: ' + str(locationInfo['longitude'])
print 'IP: ' + str(locationInfo['ip'])

1 Comment

I try to this example .But it show error
3

You can do that using ipinfo's api first go to ipinfo.io and sign up. You'll get a access token, copy it, now do pip install ipinfo now you can type this sample code:

>>> import ipinfo
>>> handler = ipinfo.getHandler(access_token)
>>> d = handler.getDetails(ip_address)
>>> d.city

or if you'll directly do d.details it will return a dictionary and you could use it as a dictionary too, it would have all things like ip address, city, country, state etc. you can also get them using like this d.country or for location d.loc, for city, as i wrote, d.city

Comments

2

https://github.com/airakesh/BeautifulSoupRecipes/blob/master/geoip.py

# Get Geolocation(Country) and hostname by passing a file having a bunch of IP addresses as the argument from the command line. Example- python GeoIP.py path-to-file-containing-IP addresses:
https://github.com/airakesh/BeautifulSoupRecipes/blob/master/sample_ips.txt

import re
import os
import sys
import subprocess
import socket

# Input file argument
ips_file = sys.argv[1]

# The regular expression for validating an IP-address                                                                                                                                                            
pattern = '''^(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)'''

def getGeoHost():
    fp = open(ips_file, 'rb')
    for line in fp:
        line = line.strip()
        addr = line.decode('utf-8')
        regex = re.compile(pattern)
        match = regex.match(addr)
        # Get hostname by IP address                                                                                                                                                                          
        try:
            host = socket.gethostbyaddr(addr)
            hostname = host[0]
        # Print Unknown no hostname is available                                                                                                                                                                  
        except:
            hostname = 'Unknown'

        # Get geolocation by IP address                                                                                                                                                                            
        get_geo_cmd = 'geoiplookup ' + addr
        geo_str = subprocess.check_output(get_geo_cmd, shell=True)
        geo = geo_str.decode('utf-8')

        # Match country name pattern                                                                                                                                                                              
        geo_pattern = '''^(GeoIP Country Edition: ([A-Z]{2})\, (.*))'''
        geo_regex = re.compile(geo_pattern)
        country_match = re.match(geo_pattern, geo)
        # Check country name is available and if not, print 'Unknown'                                                                                                                                               
        if country_match != '' and geo_pattern:
            try:
                country = country_match.group(3)
            except:
                country = 'Unknown'
        # Clubbing together in format 'IP|Country|Hostname' data                                                                                                                                                    
        geo_hostname = addr + ' | ' + country + ' | ' + hostname
        print geo_hostname


if __name__ == "__main__":

    ips_detail_list = getGeoHost()

Comments

1
import urllib.request
import json


ips = ['x.x.x.x', 'x.x.x.x','x.x.x.x']


for ip in ips:
        with urllib.request.urlopen("https://geolocation-db.com/jsonp/"+ip) as url:
                data = url.read().decode()
                data = data.split("(")[1].strip(")")
                print(data)

4 Comments

Welcome to Stack Overflow! While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.
Welcome to Stack Overflow! On Stack Overflow, the how is important, but a great part of the quality level of the site comes from the fact that people go to great lengths to explain the why. While a code-only answer get the person who asked the question past whatever hurdle they might be facing, it doesn't do them or future visitors much good in the long run. See Is there any benefit in code-only answers?
Using geolocation-db.com was already mentioned in this answer. This is just a copy of that answer, with only the for-loop added.
Yes it's a duplicated answer
0
nmap --script ip-geolocation-geoplugin <target>
Script Output
| ip-geolocation-geoplugin:
| coordinates: 39.4208984375, -74.497703552246
|_location: New Jersey, United States

https://nmap.org/nsedoc/scripts/ip-geolocation-geoplugin.html

1 Comment

This is not a Python script.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.