Easy IP-to-country lookup in Python

We’re branching into the U.S. market with our wedding registry website, Gifty. So first we grabbed a .com domain name, but we also had to make sure the price shows correctly in USD or NZD depending on where you’re from.

There are a number of tools available for geo-locating someone based on their IP address, including some free ones. MaxMind is pretty popular and nice to use, and their free GeoLite Country database did the trick for me.

Gifty runs on Python, so I wanted something I could just use in pure Python. It turns out that pygeoip is a nice Python replacement for MaxMind’s C-based API.

However, I was only interested in the country-code lookup, so I decided to strip it down and release the two-pages-of-Python version I’m using. Just grab MaxMind’s database and put the code in Python’s Lib/site-packages directory:

get geoip.py

And then to use it, simply type:

>>> import geoip
>>> geoip.country('202.21.128.102')
'NZ'

10 July 2009 by Ben    7 comments

7 comments (oldest first)

David Preece 13 Jul 2009, 20:50 link

FWIW you can do it without anything other than standard libraries. This example from a django project:

    try:
        country = urlopen("http://geoip1.maxmind.com/a?l=mykeywashere&i=" +
                          request.environ['REMOTE_ADDR']).read()
        whatever = (country == 'NZ')
    except HTTPError:
        pass #server is dead, connectivity is lost, run with default
Ben 14 Jul 2009, 09:51 link

Cheers, David. Yeah, I knew about MaxMind’s HTTP-based GeoIP service, and it’s nice and easy. However, it’s slow, and because I need to do an IP-to-country lookup on every page load, it needs to be fast.

With the offline database and geoip.py, I can do 3000 lookups per second on my machine, which is fast enough for me. :-)

David Preece 14 Jul 2009, 10:13 link

Oh! Oooohhh, ok. I do it once, on account creation…

John Hyde : Site Doublers 4 Aug 2009, 16:38 link

If your method works quickly and is relaiable then there’s no point in change.

aminoacid 11 Mar 2010, 02:19 link

Nice article man! Just like to point out there is a nice mashup of google maps with Geolocation (Ip to Country) which i use often here: http://www.astalavista.com/index.php?app=onlinetools&module=ipinfo

John Smith 23 Jul 2013, 12:56 link

This is awesome. So much faster doing it locally than having to query a remote source.

Colin 20 Jan 2014, 21:41 link

Awesome tool! I wrote some convenience functions for performance benefits and also automated the updating of the”GeoIP Lite Country” database:

__geoip_cache = {}

def country(ip, dbname='GeoIP.dat', cache=True, update=True):
"""Helper function that creates a GeoIP instance and calls country()."""
    g = None
    if cache: g = __geoip_cache.get(dbname)
    if g is None: 
        if update_db:
            update_db(dbname=dbname)
        g = GeoIP(dbname)
        __geoip_cache[dbname] = g

    return g.country(ip)

def update_db(src='http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz', dbname='GeoIP.dat', thresh=None):
    import os.path, datetime
    thresh = thresh or datetime.timedelta(days=7)
    try:
        mod_time = datetime.datetime.fromtimestamp(os.path.getctime(dbname))
    except OSError: mod_time = None
    cur_time = datetime.datetime.now()
    if not mod_time or cur_time-mod_time > thresh:
        import requests
        r = requests.get(src)
        data = r.content
        if src.endswith(".gz"):
            import gzip, StringIO #io.StringIO doesn't seem to do the job. StringIO.StringIO is legacy.
            s = StringIO.StringIO(data)
            data = gzip.GzipFile(fileobj=s).read()
        open(dbname, "wb").write(data)