Geocoding IP Addresses For Free Using IPInfoDB And ColdFusion

Posted September 29, 2010 at 7:40 PM by Ben Nadel

Tags: ColdFusion, Javascript / DHTML

Geocoding is the act of getting unknown geographic information based on existing related geographic information. So, for example, when we use Google Maps, we are often geocoding addresses; that is, we are getting latitude and longitude values based on street address (ex. 123 Main St.). While not nearly as accurate as street addresses, IP addresses are also a form of geographic information. Using services like IPInfoDB, we can geocode IP address in ColdFusion; that is, we can get the general geographic location of an internet request based on the incoming IP address.

As I was recently telling Mike Lewis, when it comes to geocoding IP addresses, I've been playing with IPInfoDB because it is both free and very easy to use. In addition to providing a web-accessible API, IPInfoDB also allows you to download an IP database for fast, local lookups. The API has no real usage limits; however, if you query the API more than twice a second, your requests will automatically be queued.

To use the API in ColdFusion, all we need is the CFHTTP tag:

  • <!--- Set the IP address that we want to geocode. --->
  • <cfset ipAddress = "71.167.205.201" />
  •  
  • <!--- Loop up the location of the given IP address. --->
  • <cfhttp
  • result="ipRequest"
  • url="http://ipinfodb.com/ip_query.php?ip=#ipAddress#"
  • method="get"
  • />
  •  
  • <!--- Check to make sure the result is good. --->
  • <cfif reFind( "20\d", ipRequest.statusCode )>
  •  
  • <!--- Parse the XML response. --->
  • <cfset ipInfo = xmlParse( ipRequest.fileContent ) />
  •  
  • <!--- Output the IP geolocation information. --->
  • <cfdump
  • var="#ipInfo#"
  • label="IP Geoclation Information"
  • />
  •  
  • </cfif>

Here, we are simply sending the target IP address as one of the URL parameters and parsing the XML response. When we run the above code, we get the following CFDump:

 
 
 
 
 
 
Geocoding IP Addresses For Free Using ColdFusion And IPInfoDB. 
 
 
 

As you can see, the response contains information about the street address and the latitude / longitude values. By default, the API returns data in XML format. If you wanted to get the response back as a JSON-encoded value, all you would have to do is add the following URL parameter to the API call:

output=json

While the above demo geocoded a single IP address, the IPInfoDB API provides a resource that allows us to geocode up to 25 IP address at a time. By using "ip_query2.php" instead of "ip_query.php", we can pass our IP address collection in as a comma-delimited list of values.

  • <!---
  • Create an array to hold our IP address locations. The IP Info DB
  • can handle up to 25 IP address look-ups at any one time.
  • --->
  • <cfset ipAddresses = [] />
  •  
  • <!---
  • Let's generate 25 random IP addresses (not sure if these will
  • all be valid).
  • --->
  • <cfloop
  • index="i"
  • from="1"
  • to="25"
  • step="1">
  •  
  • <!--- We'll randomly generate the last two octets. --->
  • <cfset arrayAppend(
  • ipAddresses,
  • "71.167.#randRange( 1, 255 )#.#randRange( 1, 255 )#"
  • ) />
  •  
  • </cfloop>
  •  
  •  
  • <!---
  • Loop up the location of all 25 IP address. When we do this, we
  • are going to use a different API (notice the "2" at the end of
  • the script name).
  •  
  • NOTE: We are explicitly turning OFF the use of timezone since it
  • requires the public API to make two more queries on their end.
  • We are trying to be kind and let them do as little work as
  • needed since we don't need timezone info for the demo.
  • --->
  • <cfhttp
  • result="ipRequest"
  • url="http://ipinfodb.com/ip_query2.php?ip=#arrayToList( ipAddresses )#&timezone=false"
  • method="get"
  • />
  •  
  • <!--- Check to make sure the result is good. --->
  • <cfif reFind( "20\d", ipRequest.statusCode )>
  •  
  • <!--- Parse the XML response. --->
  • <cfset ipInfo = xmlParse( ipRequest.fileContent ) />
  •  
  • <!--- Output the IP geolocation information. --->
  • <cfdump
  • var="#ipInfo#"
  • label="IP Geoclation Information"
  • />
  •  
  • </cfif>

In this demo, we are building an array of 25 randomly generated IP addresses. Then, we invoke the API, passing in all 25 IP addresses as a single list. In this example, I have included the API parameter, "timezone=false". This removes the timezone information from the response; but, it also puts less stress on the API and since it's a free service, we're trying to be nice.

When you batch-geocode the IP addresses, the XML response contains a collection of Location nodes:

 
 
 
 
 
 
Geocoding Multiple (Upto 25 At A Time) IP Addresses For Free Using ColdFusion And IPInfoDB. 
 
 
 

Now that we see how to geocode IP addresses using ColdFusion and IPInfoDB, let's bring Google Maps into this sexy little menage-a-trois. Once we have obtained the latitude and longitude for a given IP address, we should be able to easily place a Marker for it on an existing Google map. In the following demo, I'm going to both geocode and map our 25 randomly generated IP addresses.

  • <!---
  • Create an array to hold our IP address locations. The IP Info DB
  • can handle up to 25 IP address look-ups at any one time.
  • --->
  • <cfset ipAddresses = [] />
  •  
  • <!---
  • Let's generate 25 random IP addresses (not sure if these will
  • all be valid).
  • --->
  • <cfloop
  • index="i"
  • from="1"
  • to="25"
  • step="1">
  •  
  • <!--- We'll randomly generate the last two octets. --->
  • <cfset arrayAppend(
  • ipAddresses,
  • "71.167.#randRange( 1, 255 )#.#randRange( 1, 255 )#"
  • ) />
  •  
  • </cfloop>
  •  
  • <!---
  • Loop up the location of all 25 IP address. When we do this, we
  • are going to use a different API (notice the "2" at the end of
  • the script name).
  •  
  • NOTE: We are explicitly turning OFF the use of timezone since it
  • requires the public API to make two more queries on their end.
  • We are trying to be kind and let them do as little work as
  • needed since we don't need timezone info for the demo.
  • --->
  • <cfhttp
  • result="ipRequest"
  • url="http://ipinfodb.com/ip_query2.php?ip=#arrayToList( ipAddresses )#&timezone=false"
  • method="get"
  • />
  •  
  • <!--- Check to make sure the result is good. --->
  • <cfif !reFind( "20\d", ipRequest.statusCode )>
  •  
  • <!--- Something went wrong, so just exit out. --->
  • IP Geolocation Failed
  • <cfabort/ >
  •  
  • </cfif>
  •  
  •  
  • <!---
  • If we made it this far, then we we know our IP geolocation
  • request has succeeded. Parse the XML into a ColdFusion XML
  • document.
  • --->
  • <cfset ipInfo = xmlParse( ipRequest.fileContent ) />
  •  
  • <!---
  • Query the XML document for locations. This will return an
  • array of Location XML nodes.
  • --->
  • <cfset locations = xmlSearch( ipInfo, "//Location" ) />
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <cfoutput>
  •  
  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Geocoding IP Address using IP Info DB</title>
  •  
  • <style type="text/css">
  •  
  • html,
  • body {
  • height: 100% ;
  • margin: 0px 0px 0px 0px ;
  • overflow: hidden ;
  • padding: 0px 0px 0px 0px ;
  • width: 100% ;
  • }
  •  
  • div.mapContainer {
  • height: 100% ;
  • width: 100% ;
  • }
  •  
  • </style>
  • <!--- Include jQuery and Google Map scripts. --->
  • <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
  • <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
  • </head>
  • <body>
  •  
  •  
  • <div class="mapContainer">
  • <!-- This is where Google map will go. --->
  • </div>
  •  
  •  
  • <!---
  • Now that we have defined our map container, we should be
  • able to immediately load our Google Map.
  • --->
  • <script type="text/javascript">
  •  
  • // Get the map container node.
  • var mapContainer = $( "div.mapContainer" );
  •  
  • // Create the new Goole map controller using our
  • // map (pass in the actual DOM object). Center it
  • // above the first Geolocated IP address.
  • map = new google.maps.Map(
  • mapContainer[ 0 ],
  • {
  • zoom: 9,
  • center: new google.maps.LatLng(
  • #locations[ 1 ].Latitude.xmlText#,
  • #locations[ 1 ].Longitude.xmlText#
  • ),
  • mapTypeId: google.maps.MapTypeId.ROADMAP
  • }
  • );
  •  
  • // Loop over the geolocated-IP addresses and create
  • // markers for each of them.
  • <cfloop
  • index="location"
  • array="#locations#">
  •  
  • new google.maps.Marker({
  • map: map,
  • position: new google.maps.LatLng(
  • #location.Latitude.xmlText#,
  • #location.Longitude.xmlText#
  • ),
  • title: "Location #location.xmlAttributes.id#"
  • });
  •  
  • </cfloop>
  •  
  • </script>
  •  
  • </body>
  • </html>
  •  
  • </cfoutput>

Once we have the latitude and longitude information for our IP addresses, Google map Markers can be easily created and applied with google.maps.LatLng() instances. Running the above code gives us the following Google map output:

 
 
 
 
 
 
Geocoding And Mapping IP Addresses For Free Using ColdFusion, IPInfoDB, And Google Maps. 
 
 
 

Using randomly-generated data, this is not so interesting; but, if you can imagine gathering IP addresses from ColdFusion web application users, suddenly this map seems much more exciting.

As you can see, geocoding IP addresses in ColdFusion is quite easy when you use the IPInfoDB API. The API is free, so use it with care. The site recommends that you cache IP addresses locally or in the user's cookies so you don't have to query their servers unless necessary.




Reader Comments

Sep 29, 2010 at 8:02 PM // reply »
148 Comments

Wow . . . I can see how useful this could be. So, say you have an user logging in to check for stores selling a certain product within 50 miles, this would come in handy? Or am I missing something obvious?


Sep 29, 2010 at 9:31 PM // reply »
5 Comments

Nice post, Ben. I've been doing a lot of playing around with geolocation services too. Two other free services I've found are www.ipgp.net and www.geoplugin.com


Sep 29, 2010 at 10:09 PM // reply »
10,743 Comments

@Lola,

I think it would definitely be good to, at the very least, default to some sort of search parameters.

@Tony,

Oh cool, I haven't seen those; I'll have to check them out. A cursory glance and these look pretty good. Have you found one of them to be a better choice than the other?


Sep 29, 2010 at 10:58 PM // reply »
34 Comments

i think you can speed things up considerably using the original db (from maxmind) as a local binary file (don't bother w/the sql database approach, it's never as fast as the binary): http://www.maxmind.com/app/geolitecity


Sep 29, 2010 at 11:18 PM // reply »
5 Comments

Hmm...well it looks like ipgp.net is now a subscription service (although the api which used to be published publicly on the site still works fine for me). I'd say IPInfoDB is better, though. GeoPlugin is has some nifty tools like currency geolocation and a currency conversion tool. They also have a JavaScript web service in addition to the obligatory XML and JSON web services. Also, if you register with them they have analytics tools which they claim compare favorably with Google (I haven't tried them yet myself).


Sep 30, 2010 at 3:03 AM // reply »
9 Comments

This is really a great and interesting app...very useful..

thanks a lot for the stuff and ur's explanation


Sep 30, 2010 at 3:57 AM // reply »
15 Comments

Good stuff! A few months ago we started geocoding visitors for our online church services to show where everyone is watching from. We're using onSessionEnd to remove the visitors marker when they leave. Pretty cool to see markers appear and disappear. We went with Maxmind's web API. Not free but it's really inexpensive. If it's Sunday you can see it in action: http://faithpromise.org/icampus or there's a screenshot here: http://kyle.fm/s/f9

On a side note, you gotta love version 3 of Google Maps. Just pure awesomeness!


Sep 30, 2010 at 8:58 AM // reply »
8 Comments

THANK YOU Ben, really nice service, hopefully it stay free.


Ed
Sep 30, 2010 at 11:50 AM // reply »
12 Comments

About 2 years ago used http://www.whois-api.com for similar purpose with the function here: http://blog.1smartsolution.com/index.cfm/action:posts.entry/id:176/Getting-GEO-IP-Information


Sep 30, 2010 at 12:13 PM // reply »
1 Comments

Wow Ben, IPinfoDB's a pretty good find. I'm curious how they make money because I'd bet they're handling a ton of traffic.

It's nice they support XML and JSON. XML's pretty standard in a lot of languages, but Python's got almost native support for JSON.


Sep 30, 2010 at 12:46 PM // reply »
7 Comments

Great post Ben. I've been using IPInfoDB for a while. I do want to warn that the lookup can be highly inaccurate at times. IPInfoDB reports my alocation as Wichita, Kansas. That's about 2,000 miles off. The system is not updated regularly.

That being said, I very much like the service and it's very reliable uptime-wise.

Also, I highly recommend if you use the service to consider donating a few bucks to them. The system is operated from donations. I am certain they would appreciate a once a year donation of $20.


Sep 30, 2010 at 1:49 PM // reply »
10,743 Comments

@Paul,

Very interesting; if I am understanding the instructions correctly, you actually interact directly with their DAT file using some sort of API rather than hitting a database? Very cool.

@CF Fan, @Misha,

Glad you liked :)

@Brad,

Very cool. I like the idea of keeping the markers there only for session duration. Nice realtime feedback about the general church community.

@Ed,

Cool stuff - looks like there were even more options than I found on Google.

@Mike,

Yeah, I actually would have gone JSON, but between you and me, I didn't see the JSON option until *after* I had coded the demo :) ColdFusion works quite nice with both XML and JSON, but ultimately, JSON gets parsed into native ColdFusion objects... as I assume it does in Python as well.

As far as how they make money, no idea!

@TJ,

Maybe you were using the API that was only accurate to "planet"?? ;) I guess there are simply limitations on the mapping between IP and location. Take something like my iPhone - it has a static IP (I believe). I have to image that will always be the same no matter where I actually am in the world.

Good to hear that their goal of 99.99% uptime seems to be working out.

As far as donations, I'd be more than happy to help out. If I get value, I have no problem giving value.


Sep 30, 2010 at 1:58 PM // reply »
7 Comments

Ben, I believe the issue is how often the database is updated. For instance, when I first started using IPInfoDB my location was correct. In the last 5 months, it changed to Wichita. Other providers showed the same location, but within a week it was corrected. IPInfoDB's remains the same.Essentially, my code is the same as yours and I am using a static IP, so I can only assume its the frequency of the database updates.


Sep 30, 2010 at 2:02 PM // reply »
10,743 Comments

@TJ,

I wonder why it would start out accurate and then become less accurate. I guess I am wrongly assuming that IP-location mappings don't change (they only become more in number). The IPInfoDB databases look like they get updated monthly. I guess where ever they get their updates from also has the problem also.


Sep 30, 2010 at 2:04 PM // reply »
34 Comments

@Ben,

yes. that's how we did our geolocator:

http://javainetlocator.sourceforge.net/

but it's woefully out-of-date, nigel's been flitting round the world & hasn't updated it it quite some time.


Sep 30, 2010 at 2:09 PM // reply »
7 Comments

Ben, I think as the routing for an IP changes, those sources get updated. In my case, this change happened about the same time that Comcast overhauled the network here in Sacramento. I've seen changes in my traceroutes, and guessed that the routing was optimized over higher bandwidth routes. This is all just theory, of course.


Sep 30, 2010 at 4:27 PM // reply »
13 Comments

IPInfoDB thinks I'm 200 miles away which is the other end of the country! I'm in England. What it located was my ISP's HQ. If I can ever find a geoIP db that works very well in the UK (I've been looking for ages) I'd love to offer visitors a localised home page when they visit one of my sites.

For those visitors where the geoIP db gets it very wrong and shows them info from a location 50+ miles away then they will be scratching their head, especially if they don't recognise the location. Perhaps it's better to prompt everyone for a post/zip code.


Sep 30, 2010 at 4:35 PM // reply »
10,743 Comments

@PaulH,

The binary approach looks cool. I'm curious to see what API they provide.

@TJ, @Gary,

Yeah, I would never use this approach the only way to do things. Rather, as Gary is saying, I'd just use it as a way to potentially default a value (such as zip code) that the user could override whenever they need to.


Nov 11, 2010 at 6:06 AM // reply »
1 Comments

Hi ! It seems that infodb is down for some reason. Does anybody has the november release of ipinfodb_one_table_full.sql.bz2 or an good mirror ?!


Nov 29, 2010 at 11:42 AM // reply »
3 Comments

ipinfodb now required free registration to use service.

Correct code will be

<cfhttp method="get" url="http://api.ipinfodb.com/v2/ip_query.php" resolveurl="no" timeout="15">

<cfhttpparam type="formfield" name="ip" value="#ip#">
<cfhttpparam type="formfield" name="key" value="[your key]">

</cfhttp>


Dec 5, 2010 at 3:16 PM // reply »
10,743 Comments

@George,

Thanks for the heads up. I have some IPInfoDB code commented out. I can only imagine that when I uncommented it, it would have taken me a LONG time to figure out that their API had changed (especially since it happens inside an asynchronous CFThread). Good catch.


May 26, 2011 at 10:12 AM // reply »
3 Comments

They changed again
http://ipinfodb.com/ip_location_api.php



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 16, 2012 at 8:18 PM
Best Of ColdFusion 10 Contest Entry - HTML Email Utility
Just found this, looks good! I'm trying to run it on local, it's the 64bit version and I'm experiencing horrible lag. On average the generate.cfm processes the content change in 60-90 seconds. I've ... read »
May 16, 2012 at 6:40 PM
Maintaining Sessions Across Multiple ColdFusion CFHttp Requests
I am trying to integrate this CFHTTPsession into an application that will log into zeekrewards.com to post ads and I am not having any luck. The code works perfectly for logging into other websites, ... read »
May 16, 2012 at 2:44 PM
Creating A Sometimes-Fixed-Position Element With jQuery
Thank you, very useful technique! Worked like a charm. ... read »
May 16, 2012 at 1:58 PM
Movies As A Religious Experience
Acting can, in a way, ruin the movie-goer's experience. I used to be able to get so caught up in movies and their plots, and totally engaged. But lately, I haven't been able to as much with a lot o ... read »
May 16, 2012 at 1:52 PM
The Science Of Optimal Post-Exercise Nutrition
children of this age eat very less vegetables so u can opt for salads they will like it also carrot ,cucumber,onion and as far as pulses are concerned u can boil them ,give him along with mashed rice ... read »
May 16, 2012 at 1:34 PM
Strange ColdFusion JRUN Stack Overflow Error
Hey, Recently I updated my jrun4 using the latest updater 7 and now i am having memory issues :(:(:( any help is appreciated ... read »
May 16, 2012 at 9:56 AM
ColdFusion 10 Beta, Apache Tomcat, And Symbolic Links On Mac OSX
Hi, Now that ColdFusion 10 is out I have stumbled over this as well and I cannot figure out the proper solution. We're running virtual hosts via Apache2; the ColdFusion-applications store their fil ... read »
May 15, 2012 at 6:03 PM
Movies As A Religious Experience
@Ben, I don't know whether you'd consider this a religious observation, but it seems to me, in a sense, movies multiply how many lives we get to have. Each movie is like a little extra life we get ... read »