Skyhook Wireless: Wifi-Based Location Detection (and the handy API)

Skyhook Wireless is a company that does one thing, and does it well: wardriving. They send vans equipped with wifi-detecting equipment and GPSs (wait, is that the plural of GPS? Is it GPSii?) and log the data. Unfortunately, they do not make their data publicly available. What they do have, however, is a XML API.

With a simple HTTP POST, you can (quite accurately) determine the location of a computer based on the BSSIDs (MAC addresses) and signal strengths of the networks it sees. You receive back an easily-parsed XML document containing latitude, longitude, and street address. However, Skyhook is quite bad at figuring out street addresses; the latitude-longitude data is much more helpful.

Skyhook has a Javascript API for web apps with a special browser plugin. The C API is handy for C apps (even has a Linux version!). But those are both wrappers over the simple XML protocol.

OATT is a Sourceforge project to create an open antitheft tracker for stolen laptops. Full disclosure: I am the admin of the project. For laptops without (insert plural of GPS here), I decided to use Skyhook and created a handy Python wrapper.

To use this wrapper in other Python apps, you must do three things (not including downloading the code and cd’ing into the source.)

  1. From a shell, run “sudo”. This will save network information accessible only to root to a file. To update location, you must rerun this command.
  2. In your Python program (the OATT source must be in your $PYTHONPATH), add “import lookup” to the top of the source.
  3. In your Python program, read the contents of “lookup.results”. This is a dictionary with the following keys:
    • “address”: This is a tuple containing the house number, street, city, state, country, and zipcode, in that order.
    • “latlong”: This is a tuple containing the latitude and longitude (both with very many digits after the decimal) in that order.
    • “accuracy”: This is a value taken from the raw Skyhook data. It represents the accuracy in some sort of units.

I am not affiliated in any way with Skyhook. However, they are quite technically impressive and I believe the API should be in much wider use.

6 thoughts on “Skyhook Wireless: Wifi-Based Location Detection (and the handy API)

  1. If you change the network card, your computer’s MAC address will change. However, Skyhook looks at only the network’s MAC addresses, which are not affected by your computer’s MAC address.

  2. (Cross-posted from )

    Not working so well on OS X 10.6.3:

    Sam-Kupers-MacBook:oatt sampablokuper$ sudo python
    sh: iwlist: command not found
    Sam-Kupers-MacBook:oatt sampablokuper$ ls -al
    total 160
    drwxr-xr-x 16 sampablokuper admin 544 17 May 15:43 .
    drwx—— 6 sampablokuper admin 204 17 May 15:41 ..
    drwxr-xr-x 8 sampablokuper admin 272 17 May 15:41 .svn
    -rwxr-xr-x 1 sampablokuper admin 5625 17 May 15:41
    -rw-r–r– 1 sampablokuper admin 6224 17 May 15:41 IWList.pyc
    -rw-r–r– 1 sampablokuper admin 49 17 May 15:41 config.txt
    -rw-r–r– 1 sampablokuper admin 485 17 May 15:41
    -rw-r–r– 1 sampablokuper admin 746 17 May 15:41 lookup.pyc
    –w—-r-T 1 root admin 6 17 May 15:43 networks.pik
    -rw-r–r– 1 sampablokuper admin 6581 17 May 15:41
    -rw-r–r– 1 sampablokuper admin 8544 17 May 15:41 node.pyc
    -rw-r–r– 1 sampablokuper admin 1306 17 May 15:41
    -rw-r–r– 1 sampablokuper admin 3090 17 May 15:41
    -rw-r–r– 1 sampablokuper admin 4102 17 May 15:41 simplexmlapi.pyc
    -rw-r–r– 1 sampablokuper admin 2857 17 May 15:41
    -rw-r–r– 1 sampablokuper admin 4115 17 May 15:41 skyhook.pyc
    Sam-Kupers-MacBook:oatt sampablokuper$ sudo python
    Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29)
    [GCC 4.2.1 (Apple Inc. build 5646)] on darwin
    Type “help”, “copyright”, “credits” or “license” for more information.
    >>> import lookup


    200 OK

    access-point required in version 2.6

    Traceback (most recent call last):
    File “”, line 1, in
    File “”, line 16, in
    File “”, line 66, in parse
    latlong = float(doc.latitude._), float(doc.longitude._)
    File “”, line 79, in __getattr__
    return getattr(self._doc, attr)
    File “”, line 202, in __getattr__
    return getattr(self._root, attr)
    File “”, line 112, in __getattr__
    return delegate(*attr.split(‘__’))
    File “”, line 101, in delegate
    return self.getChildren(name)
    File “”, line 137, in getChildren
    name, self.getName()))
    node.NoSuchNode: No latitude node found as a child of LocationRS
    >>> print lookup.results
    Traceback (most recent call last):
    File “”, line 1, in
    NameError: name ‘lookup’ is not defined
    >>> exit()

Leave a Reply