Today I noticed the following post on Slashdot: Apple Logging Locations of All iPhone Users

And the article they are referring to can be found here

First I was amazed, how can Apple do this? But on second thought, they aren’t sending it yet to anybody, it is just something on the phone (and also on the phone’s backup). My next reaction was: I want to see my own map! But to my disappointment it only works on Apple Mac’s, not Windows/Linux.

(Re-)building it in Java

Because their code is open source and well explained on the website I decided to make my own version, in Java (cross platform!). Now, just a couple of hours since I read the article, I’ve got it working and it can be used as a base for extention. So I’d like to share the code!

Step 1: Getting the correct file

This step was the hardest part, technically. The backup Apple makes doesn’t just have all the files as they are on your iPhone. Instead they all have names like: “b4d1c79c2f5fc1da044c18d1066b80b39b575590″. They do however store the information in two files: Manifest.mbdb and Manifest.mbdx.

The MBDB file only contains information about the original files, and the MBDX file contains pointers into the MBDB file with the Hex-filenames used in the backup. So we need to parse both files to be able to connect the original filename to the Hex-filename.

Luckely somebody already did this in Python and posted it on stackoverflow. I took their idea and translated it into Java code.

When this was fully translated it could resolve all the filenames. This meant I could map the target file “Library/Caches/locationd/consolidated.db” to the hex-filename “4096c9ec676f2847dc283405900e284a7c815836″.

Step 2: Reading the SQLLite file

The contents of “4096c9ec676f2847dc283405900e284a7c815836″ is just a SQLLite file. For this I decided to use SQLJet, a framework that can read(/and write) SQLLite files. Using just a couple of lines of code I had all the data I need: timestamp, latitude, longitude (and more! speed, course, confidence, altitude etc).

Step 3: What to do with the geo data?

The implementation created by Pete Warden has a nice map and timeline. But at this time I wanted to have results as fast as possible. That is why chose to just output a KML file. KML is a file format used by Google Earth and other applications.

The results are far from nice (just plain ugly) but fun: click here for a screenshot

Running the code

The above code is mainly created for developers, the resulting JAR can’t be executed. But I’m aware people will want to just have the KML file, and not go through the code. That is why I’ve uploaded an executable JAR. You can get it here: (813 KB)

To run the program, extract the three JAR-files and type:

java -jar iPhoneJTrack.jar "<location of backup directory>"

For example:
java -jar iPhoneTracker.jar "C:\Users\roy\AppData\Roaming\Apple Computer\MobileSync\Backup\b4d1c79c2f5fc1da044c18d1066b80b39b575590"

This outputs a file named iPhoneData.kml, which can be loaded for example in Google Earth.

Playing with the code

I’ve pushed my code onto GitHub:

Feel free to add features and send me pull requests!

  • JohnO

    Basic question, how do I get it to run.

    Windows Vista command line:

    java Tracker.class

    Generates errors.

    • royvanrijn

      Ah yes, I haven’t made it useable yet. I’ve released it mainly for other developers at the moment..

      I’ll add a simple command line interface and description today!

  • Z

    Hello Roy,

    We very much appreciate all the work you’ve done.

    Thanks !

  • Z
  • Xavier

    Nice job!
    It work great, quite easy too use :)

  • ferdo

    Sorry, but the dates in your kml file are wrong. I used your app to check my own awk script for errors, so I found out your dates are incorrect. The number of seconds you have to add is: 978307200

  • Silvana

    EXCELLENT !!!!

  • Colin Harrington

    Could you post your code to Github?

  • Mark

    +1 for date error – this fixes it…

    public class GeoDataExtractor {

    public static final SimpleDateFormat DF = new SimpleDateFormat(“EEE dd MMM dd HH:mm:ss ‘BST’ yyyy”);

    public List extractGeoData(File dbFile) throws Exception {
    List geoData = new ArrayList();
    SqlJetDb db =, false);
    Calendar c = null;
    try {
    ISqlJetTable table = db.getTable(“CellLocation”);
    ISqlJetCursor cursor =;
    try {
    if (!cursor.eof()) {
    do {
    //Extract the timestamp (in seconds from 01-01-2001), the latitude and longitude.
    double timestamp = cursor.getFloat(“Timestamp”);
    String ts = cursor.getString(“Timestamp”);
    double latitude = cursor.getFloat(“Latitude”);
    double longitude = cursor.getFloat(“Longitude”);
    int confidence = (int) cursor.getInteger(“Confidence”);
    c = new GregorianCalendar();
    c.set(Calendar.YEAR, 2001);
    c.set(Calendar.DAY_OF_MONTH, 0);
    c.set(Calendar.MONTH, 0);
    c.add(Calendar.SECOND, (int)timestamp);
    if (confidence >= 70) {
    geoData.add(new DataPoint(DF.format(c.getTime()), latitude, longitude));
    } while (;
    } finally {
    } finally {
    return geoData;

  • S

    Can you update your java code to actually show the right time stamp please


  • ick

    Is there a step by step for the non-programmers using windows.. java console?!

  • Scott

    Hey Guys, I am very interested in seeing this work. I have downloaded everything and extracted it but I do not know where to input the information to run it. Everything that I have extracted has no .exe I am not too good with computers. If anyone can help that would be great. Thanks

  • Dutchy

    Hi Roy,

    Thanks for all the detailed info. I’m dutch also, but will write in english so others can read too.
    I have a backup from my Iphone (3gs) on my pc, on the right location.

    The only files in this backup are .mddata & .mdinfo files, along with Status.plist, Manifest.plist and Info.plist.

    So no .mdbd files in my backup directory. I read somewhere the following:”In the newer firmware versions for the iPhone/Touch, the .mdbackup files are replaced with the .mddata and .mdinfo files.”

    Is there any way I can still find my consolidated.db file?

    Thanks in advance.

    • royvanrijn

      Sorry, I have no idea how the older versions work(ed). Maybe it is time to upgrade?

      There is probably enough information about it online. But this project was initially made just for myself, and I’m not planning on making it work for older versions. I’ve open sourced all the code (see GitHub link), who knows, maybe somebody else will pick it up and add iOS <4 support.

  • Dutchy

    Ok, thanks for your reply, I’ll go and do some searching.

  • marcjeno1

    Ehmm.. is it possible to get a guide for the newbs on how to get this KML file?:)
    I dont have a MAC so cant use the program of pete but i still wanna see it on a map.

  • papav

    I would love to see my tracking info as well, but have no idea how to execute the following:
    java -jar iPhoneJTrack.jar “”

    For example:
    java -jar iPhoneTracker.jar “C:\Users\roy\AppData\Roaming\Apple Computer\MobileSync\Backup\b4d1c79c2f5fc1da044c18d1066b80b39b575590″

    Any help for the layman…

  • MinnOkie

    Is below caused because my backup is encrypted? If so it would be good to check for encrypted backups then prompt for the encryption key and decrypt the contents to build the KML file.

    C:\Users\MinnOkie\Downloads\iPhoneJTracker>java -jar iPhoneTracker.jar “C:\Users\MinnOkie\AppData\Roaming\Apple Computer\MobileSync\Backup\b3f2a964af4cd3d77cbb77a44b52931fb16db899″
    3162 files
    C:\Users\MinnOkie\AppData\Roaming\Apple Computer\MobileSync\Backup\b3f2a964af4cd3d77cbb77a44b52931fb16db899\4096c9ec676f2847dc283405900e284a7c815836
    Exception in thread “main” org.tmatesoft.sqljet.core.SqlJetException: CORRUPT: error code is CORRUPT
    at org.tmatesoft.sqljet.core.internal.table.SqlJetOptions.checkFileFormat(
    at org.tmatesoft.sqljet.core.internal.table.SqlJetOptions.readFileFormat(
    at org.tmatesoft.sqljet.core.internal.table.SqlJetOptions.readMeta(
    at org.tmatesoft.sqljet.core.internal.table.SqlJetOptions.(
    at org.tmatesoft.sqljet.core.table.SqlJetDb$2.runWithLock(
    at org.tmatesoft.sqljet.core.table.SqlJetDb.runWithLock(
    at org.tmatesoft.sqljet.core.table.SqlJetDb.readSchema(
    at org.tmatesoft.sqljet.core.table.SqlJetDb.refreshSchema(
    at org.tmatesoft.sqljet.core.table.SqlJetDb$7.runWithLock(
    at org.tmatesoft.sqljet.core.table.SqlJetDb.runWithLock(
    at org.tmatesoft.sqljet.core.table.SqlJetDb.beginTransaction(
    at nl.redcode.iphone.sqllite.GeoDataExtractor.extractGeoData(
    at nl.redcode.iphone.Tracker.main(

  • mike

    i ran the jar successfully and created a kml file. but the file is only 116 bytes long. any idea why?

  • Colin Harrington

    I adapted this code to run directly on a consolidated.db and don’t need to execute this from a backup


  • Pingback: Holden's Log » iPhoneTracker()