Skip to content

Instantly share code, notes, and snippets.

@henrik242
Last active April 19, 2025 20:26
Show Gist options
  • Save henrik242/1da3a252ca66fb7d17bca5509a67937f to your computer and use it in GitHub Desktop.
Save henrik242/1da3a252ca66fb7d17bca5509a67937f to your computer and use it in GitHub Desktop.
Read AirTag data from the FindMy.app cache and convert to GPX
#!/usr/bin/env bash
#
# Reads AirTag data from the FindMy.app cache and converts it to a daily GPX file
#
# Rsyncs the data to a web accessible folder that can be displayed with e.g.
# https://gist.github.com/henrik242/84ad80dd2170385fe819df1d40224cc4
#
# This should typically be run as a cron job
#
set -o pipefail -o nounset -o errexit
export PATH=/usr/local/bin:$PATH
DATADIR=/tmp/airtag-data
TODAY=$(date +%d)
mkdir -p $DATADIR
DATA=$DATADIR/airtagdata-$TODAY.txt
GPX=$DATADIR/airtagdata-$TODAY.gpx
TAGNAME=Foobar
if [[ $(uname -s) == "Darwin" ]]; then
TOMORROW=$(date -v +1d +%d)
else
TOMORROW=$(date --date="tomorrow" +%d)
fi
rm -f $DATADIR/airtagdata-$TOMORROW.gpx
jq -r '.[] | select(.name == "'$TAGNAME'") | .location | "\(.latitude) \(.longitude) \(.altitude) \(.timeStamp/1000 | todate)"' \
$HOME/Library/Caches/com.apple.findmy.fmipcore/Items.data >> $DATA
START='<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:mytracks="http://mytracks.stichling.info/myTracksGPX/1/0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" creator="myTracks" version="1.1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<trk>
<name>'$TAGNAME'</name>
<extensions>
<mytracks:color red="0.000000" green="0.000000" blue="1.000000" alpha="1.000000" />
<mytracks:area showArea="no" areaDistance="0.000000" />
<mytracks:directionArrows showDirectionArrows="yes" />
<mytracks:sync syncPhotosOniPhone="no" />
<mytracks:timezone offset="120" />
</extensions>
<trkseg>'
END=' </trkseg>
</trk>
</gpx>'
echo $START > $GPX
function elems() {
LAT=$1
LON=$2
ELE=$3
TS=$4
}
cat $DATA | while read line; do
elems $line
echo '<trkpt lat="'$LAT'" lon="'$LON'">
<ele>'$ELE'</ele>
<time>'$TS'</time>
</trkpt>' >> $GPX
done
echo $END >> $GPX
cp $GPX $DATADIR/airtagdata.gpx
rsync -a --exclude='*.txt' $DATADIR example.com:public_html/airtag/
@wilkyconsultants
Copy link

I’ve been following this for a while, and the best solution I found is to buy a $100 Mac and keep it on the last macOS version before Apple started encrypting the Find My cache files. I use it as a dedicated server, running 24/7, to continuously execute the script. That script updates a directory on my iCloud Drive, which syncs seamlessly with my other devices. I then built a very simple iOS app that retrieves and parses this data from the synced folder. The app allows me to select a time and date, and it returns the location history for that period on AppleMaps using the GPX structure generated by the script.

I’d love to add a couple of features to my app, like a heatmap and a paper trail, but I’m still new to Swift. I’ve been following others who are trying to decode the data through reverse engineering, and it seems like Apple is reinforcing the encryption with every update. It’s while to me—this is your own data.....................

Yea your right, I have been working on decrypting sequoia Items.data for a while now and can't see how to get the decryption key so giving up for now. I decided to build a bunch of VMs running older Macos version for now (Monterey works great, Sonoma is a bit of a challenge under VirtualBox). Have 5 VMs running under VirtualBox on a Windows PC (16GB memory 2.3Ghz cpu). I am harvesting data on 160 airtags which I feed in to my django server and serve the data via Rest API to my iOS and android app clients. Works well so far. Saves having to buy and maintain a bunch of Macs!

@saikpr
Copy link

saikpr commented Apr 2, 2025

@wilkyconsultants - which setup to do use to create the VM?

@wilkyconsultants
Copy link

@wilkyconsultants - which setup to do use to create the VM?

Most Monterey ISO's on archive.org works fine with VirtualBox with default set up. If anyone manages to get past a boot loop panic on Sonoma 14.3.1 in VirtualBox please let me know. Tried everything..

@marcelosanchez
Copy link

The best recommendation is to buy a cheap Mac that supports macOS Sonoma 14.3.1 (minimum models: MacBook Air 2018, MacBook Pro 2018, Mac mini 2018, iMac 2019, or newer).
Install macOS Sonoma 14.3.1, the last version before Apple started encrypting Find My cache files.
This allows you to read AirTag and shared item locations directly from:

~/Library/Caches/com.apple.findmy.fmipcore/Items.data
~/Library/Caches/com.apple.findmy.fmipcore/Devices.data

With this setup, you can still extract the data in plain format using available scripts.
In newer macOS versions, reading this data is practically impossible due to the encryption implemented by Apple.

@wilkyconsultants
Copy link

The best recommendation is to buy a cheap Mac that supports macOS Sonoma 14.3.1 (minimum models: MacBook Air 2018, MacBook Pro 2018, Mac mini 2018, iMac 2019, or newer). Install macOS Sonoma 14.3.1, the last version before Apple started encrypting Find My cache files. This allows you to read AirTag and shared item locations directly from:

~/Library/Caches/com.apple.findmy.fmipcore/Items.data
~/Library/Caches/com.apple.findmy.fmipcore/Devices.data

With this setup, you can still extract the data in plain format using available scripts. In newer macOS versions, reading this data is practically impossible due to the encryption implemented by Apple.

I am using a Mac Mini 2012 with Sonoma 14.3.1 for my data collection along with a bunch of VMs running Monterey. Sonoma is better as it can access shared tags as well but Monterey is a good fall back since it can run in a small Macos VM under windows. With a 16 GB memory on a windows box you can run 5 VMs with no issues getting you 5 x 32 tags = 160 on 1 box!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment