Click here to Skip to main content
11,502,503 members (65,258 online)
Click here to Skip to main content

Using IP based Geolocation - and why it's pretty much useless.

, 3 Jul 2014 CPOL 6.4K 249 13
Rate this:
Please Sign up or sign in to vote.
I've answered quite a few questions in the last couple of months about how to get the physical location of a client from a website. And people seem to get annoyed when I say: "Don't. It's no real use". But that's the truth: you can get it, but it won't be accurate. Let's have a look and see why.

Introduction

Geolocation is useful, but there are right ways and wrong ways to get it and to use it. The right way is to use a GPS device - but I don't know of any desktop device which needs or has one, and mobile devices generally make it difficult to access via the internet. For some reason people seem to want random websites not to know where they are... Laugh | :laugh:

The problem is that an IP address has a physical location - and it must be easy to get, yes?

Background

Yes, it's easy - I'll even share the code with you in a minute - but it's also completely useless. Why? Because the physical location of an IP address is not the physical location of the client: it's the location of the internet point of presence the client is using: normally their ISP's local "office" or similar.

Let's look at the background: There are two types of IP address we are interested in - Static and Dynamic.

A Static IP is one that does not change under any circumstances: if you are disconnected completely from the internet when you reconnect you will always have the same IP address. Usually, you have to pay extra for this.

A Dynamic IP is assigned when you connect, and lasts only for the lifetime of the connection. If you disconnect your router from the phone line, you will get a different IP address when you plug it back in. These are the default for domestic connections - which are most of them!

Static IP Geolocation

Static IP's don't change, so the physical location data will also never change. So let's look at an example - Codeproject.com.. It uses a Static IP, which is 65.39.148.34 (You can find this by doing a Reverse DNS on Codeproject.com) so we can look at its physical location pretty easily:

Estimated location:

IP 65.39.148.34
Country United States
Region New York
City New York
Zip code 10004
Latitude and Longitude 40.6888 -74.0203
Area and Metro codes 212 501

(Information from FreeGeoIP.net)

Hang on a moment... let's look at that:

But Codeproject is Canadia - it's in Toronto:

But the physical info relates to a company in New York, a different country all together, because they use a company there to handle the actual connection to the internet (which is very, very normal indeed).

Dynamic IP Geolocation

Dynamic addresses are surprisingly more accurate, but in a way, that's a lot worse!

When you connect via a router, the router and the ISP do a fair amount of negotiating: and one of the items they decide on is the IP address you will use. The ISP draws a free IP from its "local pool" of IPs - those that are assigned to your "local" area - if one is available, but if they are all in use then it looks further afield.  This means that (if you live or work in a city) you will normally get an IP that is registered within a couple of miles of you, maybe even less. But...it could be hundreds of miles away:

Normally I get Swansea based IPs - it's about 30Km away or so. But this is my current, and as you can see it's London based - 250Km away. But I've had ones based in Germany in the past, where the national language is different, they are in a different time zone, and use a different currency.

So the physical location you get might be close and fairly accurate - but it's just as likely to be wildly inaccurate and:

  1. You can't tell which.
  2. The client doesn't even know where it is telling you he is.

So is there any point in looking? No - not really, because you can't rely on the information you get back!

But, getting it is simple.

I recently had a problem with my home internet connection, so I threw together some software to let me monitor my IP and when it changed - so I had to get it, which is slightly complex because you have to ask the outside world what it is - you PC doesn't need to know, and querying your router depends on the make and model.

So I used FreeGeoIP which returns your IP address as CSV data, along with the physical information. Because I prefer to "do it properly" even with quick and dirty apps, I created a class called MyIPInfo to hold it all, and a method to fill the instance:

        /// <summary>
        /// Fill in the details for this instance
        /// </summary>
        /// <remarks>
        /// This works by requesting data from FreeGeoIP, which returns the available info on an IP address
        /// If none is supplied, the current address is used.
        /// </remarks>
        /// <param name="host"></param>
        private void FillInDetails(string host)
            {
            Timestamp = DateTime.Now;
            IPAddress addr = IPAddress.None;
            try
                {
                using (WebClient wc = new WebClient())
                    {
                    if (string.IsNullOrWhiteSpace(host))
                        {
                        host = "http://freegeoip.net/csv";
                        }
                    else
                        {
                        host = string.Format("http://freegeoip.net/csv{0}{1}", "/", host);
                        }
                    string data = wc.DownloadString(host);
                    string[] sections = BreakCSVLine(data);
                    if (sections.Length != freegeoipDataSectionsCount) throw new ArgumentException("Data returned from FreeGeoIP has changed format!");
                    addr = IPAddress.Parse(sections[freegeoipDataAddress]);
                    CountryCode = sections[freegeoipDataCountryCode];
                    Country = sections[freegeoipDataCountry];
                    RegionCode = sections[freegeoipDataRegionCode];
                    Region = sections[freegeoipDataRegion];
                    City = sections[freegeoipDataCity];
                    Zipcode = sections[freegeoipDataZipcode];
                    Metro = sections[freegeoipDataMetro];
                    Area = sections[freegeoipDataArea];
                    float lat = float.Parse(sections[freegeoipDataLatitude]);
                    float lon = float.Parse(sections[freegeoipDataLongditude]);
                    LatLong = new PointF(lon, lat);
                    }
                }
            catch (Exception)
                {
                // Ignore errors (it probably means the router is down...)
                addr = IPAddress.None;
                }
            Address = addr;
            }

All it does is request the info from FreeGeoIP and process it into the various data areas.

        /// <summary>
        /// Breaks a line of CSV into individual strings, working with quoted strings correctly.
        /// </summary>
        /// <param name="rawCSV"></param>
        /// <param name="sep"></param>
        /// <returns></returns>
        private string[] BreakCSVLine(string rawCSV, char sep = ',')
            {
            List<string> data = new List<string>();
            bool inString = false;
            StringBuilder sb = new StringBuilder();
            foreach (char c in rawCSV.Trim('\r', '\n'))
                {
                if (inString)
                    {
                    if (c == '"')
                        {
                        inString = false;
                        }
                    else
                        {
                        sb.Append(c);
                        }
                    }
                else
                    {
                    if (c == sep)
                        {
                        data.Add(sb.ToString());
                        sb.Clear();
                        }
                    else if (c == '"')
                        {
                        inString = true;
                        }
                    else
                        {
                        sb.Append(c);
                        }
                    }
                }
            data.Add(sb.ToString());
            return data.ToArray();
            }
You'll find the whole class in the sample download.

Points of Interest

It's surprising which pool your IP can come from: I got London, Birmingham, and Llanelli in two days of checking.

It's also annoying how intermittent disconnection problems stop happening when you are waiting for your ISP to call you back about the problem...

History

2014-07-03 First version

2014-07-04 Typos Blush | :O loads of typos....the article submission wizard needs a spell checker... Laugh | :laugh:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

OriginalGriff
CEO
Wales Wales
Born at an early age, he grew older. At the same time, his hair grew longer, and was tied up behind his head.
Has problems spelling the word "the".
Invented the portable cat-flap.
Currently, has not died yet. Or has he?
Follow on   Google+

Comments and Discussions

 
GeneralMy vote of 5 Pin
CatchExAs14-Jul-14 11:30
professionalCatchExAs14-Jul-14 11:30 
GeneralMy vote of 5 Pin
Volynsky Alex6-Jul-14 4:03
professionalVolynsky Alex6-Jul-14 4:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150520.1 | Last Updated 4 Jul 2014
Article Copyright 2014 by OriginalGriff
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid