I Know Where You Live

Credit: Hope Abrams
Credit: Hope Abrams

With a reasonable chance of success, I can obtain your location to a fair degree of accuracy. Let’s give it a go.

Obtaining your location...

Hopefully, you’ll see a table of scarily-accurate information rather than an error message. If the info is miles out (or even thousands of miles out) then you’re probably reading this at work.

IP addresses are not given out willy-nilly. They are assigned hierarchically: you are assigned an address by your ISP who buy blocks of addresses from a national registrar who has been given larger blocks of addresses by the big regional registrars (for example, ARIN in North America and RIPE NCC in Europe and most of Asia). These assignments are kept in a distributed database called the whois database. If you have a Mac OS X or Linux system, you can query the database yourself:

$ whois <IPADDRESS>

This gives you most of the information you see above. Other information may be obtained by various forms of data mining; for example, when you get a weather forecast for your home town, some organization now has a fair idea of which town is your home town.

Question: is the ability to locate you by your IP address a good thing, a bad thing or just a thing? I’d say the latter. It’s a necessary side-effect of how the Internet works. Data has to be routed from one host on the Internet to another. The problem of how to do this is only tractable because of the hierarchical block assignment of IP addresses. Connecting to a local exchange ties you down further to a fairly narrow radius. On the minus side, disreputable sites may make false promises of women in your area. On the plus side, an attempt to buy goods using your Amazon account from an IP address located in Russia will throw up a red flag.

Technical Details

I’m using a geolocation API provided by ip-api.com (yes, this is an endorsement – their service is excellent and their fair use terms are very generous). They provide a JSONP interface into their database. If you’re not familiar with JSONP, it’s a way to access third party webservices, taking advantage of the fact that a JSON-encoded object is valid JavaScript and that src attributes in script tags, unlike AJAX requests, are not subject to a same-origin policy. Typically, a JSONP URL will take a callback parameter in its query string and it’s output will be the encoded JSON object passed as a parameter to your callback function. Specifically, my code looks this:

<script>
window.geo = function(obj) {
    ...
};
</script>
<script src="http://ip-api.com/json/?callback=window.geo" defer></script>

Callback function details are as follows:

window.geo = function(obj) {
    var gEle = document.getElementById("geoinfo");
    gEle.innerHTML = "";
    // Map obj properties to human readable values
    var pM = ["IP address", "query",
        "Hostname", "reverse",
        "Country", "country", "Region", "regionName",
        "City", "city", "Postcode", "zip",
        "Latitude", "lat", "Longitude", "lon",
        "Organization", "org", "Error", "msg"],
        i, tbl = document.createElement("table"),
        tr, rowIdx = 0, td, cellIdx, n, prop;
    for (i = 0; i < pM.length; i += 2) {
        n = pM[i];
        prop = pM[i + 1];
        if (!obj[prop]) {
            continue;
        }
        tr = tbl.insertRow(rowIdx++);
        cellIdx = 0;
        td = tr.insertCell(cellIdx++);
        td.appendChild(document.createTextNode(n));
        td = tr.insertCell(cellIdx++);
        td.appendChild(
            document.createTextNode(obj[prop]));
    }
    gEle.appendChild(tbl);
    if ("success" === obj.status) {
        var mapCtr = document.getElementById("map");
        mapCtr.style.height = "250px";
        var ll = {lat: obj.lat, lng: obj.lon},
        map = new google.maps.Map(mapCtr, {
            center: ll,
            zoom: 13
        }),
        marker = new google.maps.Marker({
            position: ll,
            map: map
        });
    }
};

The latitude and longitude are fed into Google Maps (whose API is a whole lot easier to use than it is to sign up for) to visualize the data.

Obtaining location information from the browser

Depending on whether your browser supports the geolocation API, whether you click the “Get Location” button, whether you give permission for your location to be used and where you are, you should see accurate information below. This information is obtained from a variety of sources. If your device has a GPS chip, that will be used. Otherwise, something like Google’s map of wi-fi networks may be used to obtain your location by triangulation. If you’re not using wi-fi, then the accuracy will be less impressive.

The API is very easy to use. You basically define a success callback and an error callback and then pass them to navigator.geolocation.getCurrentPosition, like this:

gEle = document.getElementById("geoinfo2");
var pre = document.createElement("pre");
gEle.appendChild(pre);
if (!("geolocation" in navigator)) {
    pre.innerHTML = "Geolocation is unavailable";
    return;
}

var showGeo = function() {
    var locSuccess = function(pos) {
        var lat = pos.coords.latitude,
            lon = pos.coords.longitude,
            tbl, tr, td, rowIdx, cellIdx, mapCtr;
        gEle.innerHTML = "";
        tbl = document.createElement("table");
        rowIdx = 0;
        tr = tbl.insertRow(rowIdx++);
        cellIdx = 0;
        td = tr.insertCell(cellIdx++);
        td.appendChild(
            document.createTextNode("Latitude"));
        td = tr.insertCell(cellIdx++);
        td.appendChild(document.createTextNode(lat));
        tr = tbl.insertRow(rowIdx++);
        cellIdx = 0;
        td = tr.insertCell(cellIdx++);
        td.appendChild(
            document.createTextNode("Longitude"));
        td = tr.insertCell(cellIdx++);
        td.appendChild(document.createTextNode(lon));
        gEle.appendChild(tbl);
        mapCtr = document.getElementById("map2");
        mapCtr.style.height = "250px";
        showLocation(lat, lon, mapCtr);
    },
    locError = function(e) {
        pre.innerHTML = "";
        pre.appendChild(
            document.createTextNode(
            "Unable to obtain location information: " +
            e.message));
    };
    navigator.geolocation.getCurrentPosition(
        locSuccess, locError);
};
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Get Location"));
btn.onclick = showGeo;
pre.appendChild(btn);

The geolocation API can also give you periodic updates. See the
MDN documentation
for further information.



Leave a Reply

Your email address will not be published. Required fields are marked *