Geocoding based on an IP Address

November 13, 2007 · Print This Article

Okay, so I’m on a bit of a geocoding kick here. Previous posts have discussed geocoding when you have a physical street address. But obtaining an address can be obtrusive, and the dataset used is North America-centric. This post focuses on very quickly geocoding a user’s location based on their originating IP address with MaxMind’s GeoLite City database and Java API.

There are a number of reasons why you might want to determine a user’s location based on their IP address:

  • Center a map mashup on the user’s location
  • Serve localized content, e.g. language, currency, time
  • Reduce credit card fraud (this seems to be the most commercial use at present)
  • Target marketing and ads

The biggest problem with geocoding by IP address is that it can be inaccurate for many IP addresses. This is because the coordinates for a given IP address are for the organization that owns the IP address block, and not necessarily the location of the end user of that IP address. Complicating this further are those users who connect via a proxy — e.g. AOL users. So private IP’s, VPN’s, proxied browsers, internal network blocks, and so on are difficult to geocode.

Using the GeoLite City Database on Your Server

You have two download options: CSV and binary. If your project requires that you import data into MySQL, you can use the CSV option, but it is much slower and requires more effort to setup. Binary is your best bet, and is what I used.

I installed the GeoLite City binary on both a Windows development PC and a Linux server. On Windows, download to your PC, and extract using WinZip or similar tool. On Linux:

$ wget http://www.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
$ gunzip GeoLiteCity.dat.gz
$ mv GeoLiteCity.dat /path/to/database/location/GeoLiteCity.dat

Import the Java API into your current project in your IDE of choice. I’m using JBuilder (boo, hiss). There are also API’s for C, Perl, PHP, C#, Ruby, Python, VB.NET, Pascal, and JavaScript.

Using the Database (IP Address to Latitude and Longitude)

1) In your class file, create a LookupService object, specifying the location of the database you extracted. Then create a Location object for the IP address you want to geocode:

LookupService lookup = null;
try {
lookup = new LookupService(PATH_TO_DATA, LookupService.GEOIP_MEMORY_CACHE);
} catch (IOException e) {
System.out.println(ex.getMessage());
ex.printStackTrace(System.err);
}

Location location = lookup.getLocation(”62.75.185.174″);

2) Then you can extract location information from the Location object, including country, region, city, postal code, latitude, longitude, area code, and timezone.

String city = location.city;
float latitude = location.latitude;
float longitude = location.longitude;

If you create two Location objects from LookupService, you can calculate distance between them with:

double distance = location1.distance(location2);

3) Remember to close the database connection. Data access is thread safe, by the way.

lookup.close();

Note that to use GeoLite City on a public web site, you must include the line “This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/” in any documentation or promotional materials.

Using MaxMind’s City Web Service

If you prefer, you can purchase 50,000 IP address queries for $20. This may be more suitable if you’re using a shared hosting space or if you don’t want to download the monthly database updates. It also will give you better accuracy than the free GeoLite City database.

The broad strokes are below (this example uses the excellent Commons Lang and Commons IO libraries):

String wsUrl = new StringBuffer(”http://geoip1.maxmind.com/f?l=”).append(your-license-key).append(”&i=”).append(ipaddress).toString();
URL url = new URL(wsUrl);
String results = IOUtils.toString(url.openStream());
String[] arrResults = StringUtils.split(results, “,”);

// arrResults[0] = country
// arrResults[1] = region
// arrResults[2] = city
// arrResults[3] = postal code
// arrResults[4] = latitude
// arrResults[5] = longitude
// arrResults[10] = error

GeoLite City or GeoCity Web Service or Geobytes?

MaxMind claims that the GeoLite City Database resolves IP addresses to cities 70 percent of the time, whereas their paid product and web service correctly resolve 80 percent of IP addresses. Review the entire accuracy table.

The UK (46%), France (55%), Italy, Switzerland, New Zealand, Germany, Australia, Argentina, and Japan all have under 70 percent success rates.

Other Services

There are plenty of good IP geocoding services out there, and the two that seemed to offer the best features, price, and ease of use are MaxMind and Geobytes.

Geobytes offers a $49 developer’s license, good for all the desktop tinkering and evaluation you want. But plan on spending at least $500 a year for a server license (10,000 lookups per day), and upwards of $25,000 for an enterprise license. They do have a free JavaScript web service (GeoDirection) that you can use to redirect users based on geographic location, which is very functional for that specific purpose.

MaxMind has an attractively-priced license fee, a free Lite database, and an inexpensive web service that can be used. Geocoding an IP via MaxMind is painfully simple, which is why I focused on their products in this post. Another provider is Ip2Location.

Other recent posts on geocoding:

Comments

3 Responses to “Geocoding based on an IP Address”

  1. Bret on January 13th, 2008 1:47 pm

    Id like to display a news RSS feed on my site.

    The differnce is, Id like news to be seen based on the persons IP / physical location.

    EG: Las Vegas news shown when a person from Las Vegas is viewing the site.

    Im trying to absorb all the info you have provided I Geo Targeting, etc…but not real sure how to use it for this application.

    Thx for any ideas!

  2. Bret on January 13th, 2008 1:48 pm

    Id like to display a news RSS feed on my site.

    The differnce is, Id like news to be seen based on the persons IP / physical location.

    EG: Las Vegas news shown when a person from Las Vegas is viewing the site.

    Im trying to absorb all the info you have provided I Geo Targeting, etc…but not real sure how to use it for this application.

    Thx for any ideas!

  3. Joe Fission on January 15th, 2008 9:28 am

    I’d probably set a cookie, and map the user’s location to a feed, so as to save processing each visit.

    In Java, I’d set up a filter that looked for a cookie. If it didn’t exist, I’d grab their IP, look it up in GeoLite, and map it to one of my feeds. If the IP didn’t resolve, GeoIP will put you somewhere in Oklahoma or Alabama or something like that, so I’d map that to the top stories feed.

    Shaun

Got something to say?