AirTag Hacking

Liam Davies

Issue 79, February 2024

We recently picked up a few of Apple’s popular AirTags to experiment with, and quickly realised it’s not possible to track them on anything other than Apple’s devices. In this project, we learn how these awesome devices work, and show you how to develop a cross-platform Flutter app that lets you track them anywhere!


This project is an experiment and will not be released as a finished app on the Play Store (or any other app stores). It shouldn’t be used for tracking your mission-critical items, because our code is definitely not bulletproof. We encourage contribution to our open-source code, but please do not rely on it!

As another point of discussion, we’ve seen a lot of online articles rightfully concerned about malicious use of AirTags to track people or their valuables without their knowledge. As this project provides accurate historical and locational information of a tracker, please use it responsibly and only with your own property.


Apple’s AirTags are one of the coolest production-scale products that have come to market in the last few years, and we absolutely love how simple yet effective they are. They can be used to keep tabs on anything - from your wallet to your car.

At the price of a week's worth of coffee, you can get a real-time location tracking device that gives you a piece of mind on any of your valuables with virtually no ongoing costs.

How It Works

Bluetooth Low Energy (BLE) trackers have been around for years. They’re very simple devices on paper: A small battery and a low-energy Bluetooth Radio to broadcast its presence periodically to nearby devices. Coupled with a speaker for audibly announcing the device’s presence and advanced chips like Apple’s Ultrawide Band (UWB) chip, these devices can be loaded with some clever tech.

Apple’s AirTag is a BLE chip like any other, and if you’re reading this, you’re likely familiar with how they work. By leveraging a massive network of iPhones and iPads around the world, nearby Apple device will frequently detect and report the tag’s position anonymously.

The Problem

An Apple AirTag can be detected by any Bluetooth LE-compatible device, including Androids. By using an app like AirGuard, you can even make AirTags ring with any device if it’s in range.

However, only devices running iOS 14.5 or later can actually report AirTags to the Apple network. To view the location of AirTags, only iPads, iPhones and Macs can be used. The cross-platform web-based version of Find My device can’t be used either.

This aligns with Apple’s long-standing position of making their devices and services as exclusive as possible. It makes sense from a business perspective, but from a consumer perspective, it’s frustrating to not have access to a powerful tracking network if you don’t happen to have a device with a fruit logo on the back.

We’d love to see another large competitor such as Google deploy their own platform for BLE tracking but, before they do, we’re currently stuck with much less ubiquitous platforms such as Tile and Chipolo. Or... are we?

Our Solution

It’s not really possible to get around the hurdle of not using Apple products for tracking AirTags.

However, we found an interesting alternative to not carrying around an iPhone just to see where your valuables are. By using an old MacBook with some Python code running on it, we can extract real-time locational AirTag updates. From there, we can do whatever we want with the data, such as, say, displaying the data on a mobile device it was never intended to be displayed on. Couple that with a dedicated database and a cross-platform fully-custom user interface, and we’ve got an awesome platform for AirTag experimentation.

We also managed to extract even more tracking information than Apple provides with the stock Find My app:

  • Unlimited historical information of tracked item
  • Altitude
  • Serial Number
  • Exact GPS coordinates
  • Path Tracking (over past hour, day, week, etc)

We’re very proud of this project, so let’s dig in!

Getting Started

We’re using an unused MacBook as the ‘server’ for our project. We’ll admit, it’s probably cheating to use a device from the very ecosystem we’re trying to avoid, however, Apple’s Find My platform is very secure - we won’t really have a way of accessing locational data without one. Used MacBooks can be found very cheaply and as long they can run the Find My Items platform, it’ll work fine (speed will vary, though!).

We installed the TeamViewer software on the MacBook, making sure to use the Unattended Access version of the software. This way, we can throw the MacBook in an unused corner of our office and let it run 24/7. Make sure it has plenty of ventilation and a stable source of power. We’d suggest turning the brightness of the screen to minimum, setting the sleep timer to Infinite, and installing a temperature-monitoring application to prolong the life of power delivery components on its logic board.

However, the bigger problem is that you can’t set up an AirTag without an iPhone or iPad. To do this, you’ll need to borrow a friend’s iPad or iPhone, sign in with your Apple ID, link the AirTag with your account and then sign out again. It’s a bit of a fuss, but once it’s linked, the original iPhone or iPad doesn’t need to be signed in for everything to work.

Basic Setup

There isn’t any easily-accessible API for accessing information through Apple’s Find My Device service. Luckily for us, Apple leaves all of its currently cached Find My Device data in an incredibly handy file located in the depths of the Mac’s application data. Don’t believe us? If you’re on a MacBook, open Terminal and run this command:

cat $HOME/Library/Caches/

Well, that was easy. Yep, it’s plain JSON. This is why we barely consider this “hacking”: Apple is essentially handing the locational data to us on a silver platter.

We’ll just need to write a Python script that monitors this JSON file for changes, and uploads the data to our database of choice whenever we get an AirTag update.

(Note that sometimes we found that the MacBook would throw a permission error for accessing this file. To fix it, you’ll need to run the following chunk of code)

sudo chmod a+rwx $HOME/Library/Caches/

As usual, we’ve probably overengineered this project, but we’re very proud of what we’ve managed to accomplish. While we didn’t develop this project from absolute scratch - we used a lot of existing libraries to make everything tick - we’ve essentially written a full-stack application. We’ve written code for managing the backend database, the Python script required to source tracking data, and the front-end Flutter application.

We’ve tried to be as platform-agnostic as possible where we can be. The Flutter app can be compiled for any mobile device, Android or not, and the InfluxDB system can run anywhere that supports Docker containers. As expected, the Getter program can only run on a Mac, but besides that, everything should play nicely with any device you have.

The ‘Getter’

First off, we need to extract the data from our MacBook’s Find My Device program and check that we can format and parse it. We’re using Python for this, but any program that can read and manage JSON format data will do this easily. We’re calling this program the ‘Getter’, and it’ll be running 24/7 on our MacBook.

We need to install the InfluxDB client for our Getter program to work correctly.

pip3 install influxdb-client

The Python code itself for the Getter is around 90 lines of code. We’ll only go over the important bits here. The full code is available in our project files if you’re not interested in the nitty-gritty.

The header of our file includes all of the parameters for finding the data, connecting to the InfluxDB server, and so forth. There are a two things in this script you MUST change:

  • The ‘token’ variable. This is your InfluxDB API token.
  • The ‘url’ variable - this is the URL of your database. You can use a direct IP for this if you prefer, however you may run into issues with TLS certificates. We’ll explain this shortly. If you’re using HTTP, don’t use https:// at the beginning - use http:// instead.
import influxdb_client, os, time
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS
import json
import string
home_dir = Path.home()
items_dir = "Library/Caches/"
items_file = ""
token = "ekdJSdn23vrTgaohdBFAqg8_ddsg233p3hV7vsT7cP-EMk8Ea_UKGsJDx94dCnoLOjA7_PCXdgbFLCj9fsdjvnQ=="
org = "diyode"
url = ""
interval_seconds = 5

(Obviously, we’ve substituted example values here.)

The other parameters can be changed if you’d like to further refine the project. Note that the ‘org’ and ‘bucket’ names can be left as-is, unless you’ve created different buckets and organisations in InfluxDB.

Our main code loop is fairly simple. It just opens the Items.Data file every time we go through in our while loop, and uses the JSON library to read the data on each item in it. Accessing any part of a JSON object in Python is dead simple - just load the JSON with .load(file), and then access the desired field with item[“field”] as shown above for the item’s name. We do some additional processing to simplify the item’s name so we can put it into the database with a unique key.

while True:
  file = open(home_dir / items_dir / items_file, "r", encoding=’utf-8’)
  items = json.load(file)
  for item in items:
    name = item["name"]
//Simplifies item name.
measurement_name = ‘’.join(filter(lambda g: g in set(string.printable), name))
measurement_name = measurement_name.replace(" ", "_").lower()

This code checks if we’ve already seen this tracker point - that is, this item’s timestamp is the same as last time we looked at the Items.Data file. If it IS different, we know the AirTag service has received a new point and so we continue running our database entry code.

Get Time Information

last_seen = int(item["location"]["timeStamp"] / 1000)
#If this is the first time seeing this item in the dictionary
if measurement_name not in last_updated_times:
  last_updated_times[measurement_name] = last_seen
  # If it IS in the dictionary, 
  # check if the time has changed.
  if last_updated_times[measurement_name] == 
  # If it’s the same time we’ve last seen the 
  # tracker, don’t update it again.
    last_updated_times[measurement_name] = last_seen

The last bit of code we’ll quickly check out is actually submitting the points to the database. The JSON file from the Item.Data file has a fairly simple format:

InfluxDB has fields for its points, so we can substitute all of the data we received from the JSON object straight into a measurement point.

measurement = (
  .field("name", name)
  .field("battery", battery)
  .field("last_seen", last_seen)
  .field("lat", latitude)
  .field("lon", longitude)
  .field("altitude", altitude)
  .field("address", full_address)
  .field("emoji", emoji)
write_api.write(bucket=bucket, org="diyode", record=measurement)

The rest of the code is in the project resources if you’d like to take a look! After we’ve saved the Python file to anywhere on our Mac’s disk, we can use this command in a Terminal at the Python file’s directory to run it:


This Python will now run forever and display output like this as it finds new points:

New tracker update for Liam's Backpack.
{‘liams_backpack’: 1701867364, 
‘liams_wallet’: 1701815005}
Seen 0.14 hours ago

You can press Ctrl+C at any time to terminate the script.

Backend Compute Engine

We have to find somewhere to store our backend data when our Getter program transmits it. We could run our database on a local machine on our network, however, there are a few issues associated with this approach - mostly relating to security.

Wherever our database is stored, our Flutter app will need to retrieve data from it anywhere on the Internet. Running a machine at home specifically for this purpose is possible, however, you will need to expose running ports to the Internet.

Additionally, if your machine’s internet goes down for whatever reason, you’ll have no way of querying or saving data in real-time. If you already have a home server, great, but if you don’t, you’ll have to have a computer running 24/7 for this to work properly!

For this reason, we chose to use a cloud computing platform to host our database. We chose Google’s Compute Engine service. It sounds (and looks) intimidating, but this service allows users to spin up virtual machines that can run any software you desire. Each one has virtual computer hardware which can be configured to meet performance requirements of your needs.

There are many alternatives to Google Compute Engine, such as Azure Cloud Computing, Amazon Web Services and DigitalOcean Droplets - use whatever you prefer! Most of these platforms offer a free tier of computing time, sometimes with varying conditions. Google currently offers a E2-Micro virtual machine with 1GB of RAM, 2 vCPU cores, and a 10GB persistent disk in its free tier, which is what we went with. There are a few strings attached, such as requiring creation on a select few US-based servers, but overall, it’s a good deal for free computing time. Since our database isn’t exactly serious number-crunching, it was a good option for us.

Once we finished choosing options for our machine, we can click on the SSH button and directly connect to the command line in the browser. No downloading or messing around with local SSH keys required!

Since we have a blank virtual machine, we have a few things we still need to set up before we can start feeding our AirTag data into it. We first installed Docker, a platform that allows us to easily run apps and services with almost no local configuration. It has probably saved us hundreds of hours over the years not having to manually download and compile Linux programs.

Head to to get instructions to install it, as there are a few steps. To test that everything is working, run:

Woop! Looks like everything is ready to go.


Let’s install InfluxDB, the backend database that will store all of our generated data points from our Getter program. InfluxDB is unique in that it is specifically designed to be a time-series database. Time-series databases are effective for storing metrics about systems that will change over time - who knew! You can choose to use any database system you want, however, you’ll need to rewrite and recompile code for our Getter and frontend application, implementing clients for your database of choice.

Let’s install it with Docker:

sudo docker pull influxdb

And run it like this:

sudo docker run influxdb

We now need to set up our InfluxDB container. Run this command:

docker exec -it influxdb influx setup

InfluxDB will then ask you a variety of questions to set up your database. The organisation can be set to whatever you would like, however, if you want InfluxDB to work with our Flutter app, you need to set the bucket to ‘tracker’. If you’re tight on disk space, you can also choose to not have an infinite Retention Period.

You should be now able to access InfluxDB by visiting the Public IP of your Compute Engine.

You can create your login info here.

After logging in, you should be greeted with this screen. At this point, you can experiment with creating new queries with any language to check everything is working.

Adding TLS

See that lock icon in your browser’s URL bar? That means you’re communicating with our website with HTTPS/TLS, which is a purely encrypted communication channel. It might not be 100% essential for reading a magazine, but when you’re paying with your credit card online, sending sensitive information, or say, sending GPS information of your valuables over the Internet, its a great technology to utilise. To be clear - this is optional. You don’t have to use TLS, but if you have an extra bit of time setting up this project, we’d strongly suggest it.

By default, InfluxDB runs on unencrypted HTTP. If you’re on public WiFi, this could expose your GPS data when queries are made. To add TLS, we need to enable it in our InfluxDB settings and sign a certificate on our server side.

Signing Certificate

In our first test run of using TLS, we signed our own certificate using the openssl command in Linux. While this is technically encrypted, when we connect to the database server, our browser, backend Getter and front-end app don’t trust the certificate and throw a “Not Secure” error.

After all, we could’ve been anyone signing it! We need someone to vouch for our authenticity, or a “Certificate Authority” as it’s known in the web world. We could pay for an SSL certificate, but we opted to use CertBot with Let’s Encrypt to make this work.

You don’t have to be doing this exact project to find this useful - if you’re developing and hosting your own website, this process will come in handy!

Head to and you can learn about how to install it. After installing it, you can run this command to tell it to auto-sign a certificate for you:

sudo certbot certonly --standalone

Note that you will need to expose port 80 and 8080 on your virtual machine for the CertBot verification to work correctly, as shown below for Compute Engine.

And boom, we’re done! After refreshing the page and crossing our fingers, connecting to our InfluxDB server now has no security errors - our computer is happy with the secure TLS connection. Newer versions of Google Chrome don’t actually display the green lock icon, but clicking on the connection dropdown shows the connection is secure. Great!

We can also see more information about our certificate in the Chrome certificate settings.


We don’t often develop our own user-interfaces for our DIYODE projects. Most of the time, we stick to using an existing platform to do the cool-looking stuff for us. Blynk, Grafana, or Arduino Cloud are some popular examples in the Maker community.

However, we really wanted to dial in our program so we have a ton of control over the look, feel and functionality of our front-end tracker. It’s worth noting that our Flutter application is read-only: it has no control over the AirTags, including marking them as lost, ringing the inbuilt-speakers or renaming them. To do any of that, we’d have to implement additional communication with our MacBook’s getter application and potentially deal with Bluetooth libraries.

Flutter is a front-end UI development platform that is designed to run on anything. If a program compiles for an Android phone, it’ll require minimal changes to run almost exactly the same way on an iPhone, desktop computer or tablet. This is in contrast to platforms like Apple’s XCode and Android-based Java Apps - these systems have almost no cross-compatibility when compiled natively.

User Interface

Developing a nice-looking UI in Flutter is quite simple, but it requires some good knowledge and understanding of the Dart language. It’s not a drag-and-drop UI creator, but if you’ve had experience in Java, C++, or any other object-orientated programming language, Dart isn’t much different.

If you’re not interested in the ins-and-outs of UI development, you can download the source code from our GitHub repository and compile it for yourself. However, you will need to change some things, as, by default, it won’t compile properly. You will need to install Android Studio, which we'll go over shortly.

Create a file called ‘secrets.dart’ under the ‘lib’ folder. In this file, you’ll need to fill out the following variables, substituting in your own InfluxDB API key and server IP address. Make sure to add ‘https://’ to your IP if your server is set up to use TLS/HTTPS.

// InfluxDB info  
var secret_url = ‘https://YOUR_INFLUX_DB_URL_HERE:8086’;  
var secret_influxAPIkey = ‘PiikHmRKLagPus84xwtw0FmONrSDSf1l0LX4uw1PwXW

On the topic of HTTPS, you’ll see that we’re loading a Let’s Encrypt certificate in the main.dart file. While we downloaded this directly from Let’s Encrypt’s website, you shouldn’t take our word for it - we’d encourage you to download a copy for yourself and replace ours for security reasons. Or, if you’re signing/using your own, upload it and rename the variable in the main.dart file accordingly.


A ‘Future’ is a type of object in Flutter that is intended to make your life easier when working with asynchronous functions. We’ve used them extensively throughout our project.

When we program an Arduino, for instance, we have to ensure that our programs can run without hanging when doing certain things. Because all code is executed sequentially, any time-consuming tasks will naturally delay the other tasks after it. The most time-consuming task in our DIYODE Tracker app is fetching the data from the InfluxDB server. Depending on how much data you’ve asked it to fetch, and where your server is geographically located, this could take a few seconds. We don’t want our app freezing whenever we request data from the server, so we’re requesting data asynchronously with a Future. When calling a function that returns a Future (i.e. our expectedly time-consuming task), we add the ‘await’ keyword to the function call. This tells Flutter that it’s okay to continue something else while we wait for this function to execute.

Future<List<Tracker><<ED>> getTrackers() async {
  List<Tracker<<ED>> trackers = InfluxDB.getTrackers();
  return trackers;
Future<void<<ED>> functionExample() {
  List<Tracker<<ED>> trackers = await getTrackers();

This can be a little confusing at first, but once you’ve wrapped your head around Futures, it’s an extremely powerful method of doing many things at once without slowing down your app.

Querying InfluxDB

Next, we need to fetch data from our InfluxDB database over Flutter.

We’ll need to do two queries. The first one will be fetching all of our currently present trackers in the database.

import "influxdata/influxdb/schema"
schema.measurements(bucket: "tracker")

When we run this command, we’ll get a result of all currently tracked measurement types in the bucket:


The second query will actually fetch the tracker points for each tracker, according to how many hours we’ve requested.

from(bucket: "tracker")
      |<<ED>> range(start: -${lastHours}h)
      |<<ED>> filter(fn: (r) => r["_measurement"] == "$trackerName")
      |<<ED>> pivot(rowKey: ["_time"], columnKey: ["_field"], valueColumn: "_value")

There are a few tricks we’re using here to make the query work as expected. First, we’re only selecting a certain number of hours with the ‘range’ command. We then filter it only by our current tracker name - ‘liams_wallet’, and finally pivot the whole table. This collates every record that was entered at the same time into its own row, complete with columns corresponding to those records.

Once this query finishes running, we’ll receive a list of all points for the time and tracker requested.

var foundPoints = await service.query(fluxQuery);
int numPoints = 0;
TrackerPoint last = TrackerPoint();
await foundPoints.forEach((record) {
  TrackerPoint tp = TrackerPoint();
  tp.time = record["last_seen"] ?? 0;
  tp.address = record["address"] ?? ""; = record["lat"] ?? 0;
  tp.lon = record["lon"] ?? 0;
  tp.alt = record["altitude"] ?? 0;
  tp.battery = record["battery"] ?? 0;
  tp.emoji = record["emoji"] ?? "";
  tp.owningTracker = this;
  displayName = record["name"] ?? "";

We can then create our own Tracker Points with the corresponding records. We reference records from InfluxDB in much the same way as a Python Dictionary - by using square brackets. The double ?? tells Flutter to fill in an alternative value if the field can’t be found in the record.

Google Maps Integration

While being able to see the location of your valuables is good, actually navigating to them is just as important! Unfortunately, we don’t have enough time to implement our own navigation code, so we’re delegating it to Google Maps.

We don’t need to integrate countless APIs to make this work, either. It’s as simple as opening a URI (Universal Resource Identifier). You’ve probably seen websites have links to stuff like “tel:+61123123123” or “” - this is exactly what a URI is, and we’re using a schema specifically for a geolocation - the “geo” tag in this case.

To open a “geo” URI of Sydney, for example, we can open this URI:


Opening a URI in an Android phone will result in a pin dropped roughly around the Sydney area, with a label of “Test”. We can then press “Directions” to let Google Maps figure out the rest. Cool!

import ‘package:url_launcher/url_launcher.dart’;
class MapUtils {
  static Future<void<<ED>> openMap(
      double latitude, double longitude, String name) async {
      final uri =
      if (await canLaunchUrl(uri)) {
        await launchUrl(uri);
      } else {
        print(‘Could not open map.’);

Here is the function we wrote to launch a Google Maps window of any latitude and longitude with a label. We can call this from our “map” button in our slide-out drawer.

The result is pretty awesome - it shows an exact location of the tracker, including a street view if desired. The street view is great for getting an idea roughly where in a building a tracker may be.

Android Studio

Flutter can run on a few different Integrated Development Environments (IDEs), but we’ve chosen Android Studio for its direct integration with Android Emulators and debugging tools.

You can head to the Android Studio website to download and install it. After doing so, you’ll need to install Flutter from the Plugins screen.

Navigate to the project creation screen in Android Studio, and create a new Flutter Project.

You’ll then be greeted with the main screen of Android Studio. From here, we can write our Flutter code, and compile the APK file ready for our phone.


You’ll need to use some sort of Android debugging platform to see the results of your code - in other words, a phone to test and debug the app. There are two methods for doing this.

The first is an Android phone connected to the development machine’s WiFi. To set this up, you’ll first need to enable Developer mode on your phone. This varies from model to model, so head to Google and search “developer mode ” for more information. After you’ve done that, go to Android Studio, navigate to the Debug tab and add an Android device over WiFi. From the Debug menu, enable “Use Wireless Debugging” and add a new device with the QR code shown in the Android Studio application. After the pairing process is completed, you should have a debugging connection established between your phone and the development PC.

The second option is to create an Android Emulator within Android Studio. This acts as a virtual phone in your computer, complete with WiFi, Bluetooth, touchscreen emulation and a full filesystem. This is a handy option if you’d like to test your app on phone hardware you may not currently have access to, you’d otherwise prefer not to debug your app on your real phone. After clicking on the “Virtual” tab in Android Studio, create a new Android device with your desired model and software version. The main downside of this approach is that it uses a substantial amount of disk space on your computer.

Image Credit: Brian Fraser

Either way, you should now be able to run our Flutter app by clicking on the green Play button in the top right corner of Android Studio. If this is the first time you’ve compiled your App, this could take a few minutes to compile. After compilation, it’ll automatically upload, install and open your app. Awesome!

Hot Reload

By far our favourite feature of the Flutter software development package is Hot Reload. In Android Studio, just hit Ctrl+S on your keyboard to save the current code file, which will immediately be reflected on the debugging device. You’ll see this in the Android Studio console:

Performing hot reload...
Reloaded 1 of 1034 libraries in 410ms.

And, just like that, your phone immediately updates with the new code. It’s awesome.

This saved us hours over the course of developing our DIYODE Tracker. It’s extremely handy for tweaking layout, theme and interaction settings to check everything feels and looks nice. The main limitation of Hot Reload is that most app logic will need a re-compile - it’s mostly useful for small tweaks that would otherwise waste time recompiling.


After we were happy with the progress for our DIYODE Tracker app, we exported it to our Google Pixel phone and watched it as we did some travelling.

Immediately, we were very happy with how accurately the app shows our tracked AirTags. Zooming in lets us have sub-meter precision in many cases. However, it won’t ever be 100% accurate, because the reported AirTag location is based on the reporting Apple device, not the AirTag itself.

We were astonished with how quick AirTags show up in new places in the app. Because our Getter script is constantly monitoring the Find My Device program, in some instances we detected the location of our tracked AirTags within minutes.

We also found the additional historical information incredibly useful. Apple doesn’t normally show this, but seeing how your valuables have changed positions over time could be indispensable for checked baggage on flights, for example.

The performance of the app itself is also great, however, it does suffer from stuttering while loading the OpenStreetMap view. Because this map is rasterized (i.e. it loads images instead of lines and curves), it tends to be quite slow when quickly moving around the map and zooming into tracked AirTags. In future, we’ll be looking into a better map rendering package to speed up rendering.

Where To From Here?

There are many different ways to improve this project. We’ve made this whole project open-source so you can tinker and improve any aspect of it you wish!

Starting with the Getter and back-end database, we could write further software to directly integrate with Apple’s FMIP service and mark AirTags as lost or rename them. This would require either some serious application hacking or a potentially dodgy mouse-and-keyboard emulation program. You could also go down the route of using Apple’s API for this, but we haven’t looked into this.

Image Credit: AppleInsider

One feature we’d really like to see in our DIYODE tracker is the ability to find AirTags audibly. It’s already possible with apps like AirGuard and Tracker Detect on the Google Play Store, however, these aren’t designed to actually track the location of a personal AirTag. Some research could be done into correlating a serial number or device ID from the Getter program to a physical Bluetooth device nearby. If there is a match, the device is a personally owned AirTag and can be rang audibly at the request of a user.

From a broader perspective, we’re looking forward to when Google introduces their own competitor to the BLE tracker market. There are some rumours around development of a tracking platform releasing for Google/Android phones sometime this year. While both devices can currently track AirTags travelling with a person for security reasons, we’re interested to see how much cross-platform use these future competitors will have. We have our doubts - both companies know Android users will most likely buy Google’s AirTag equivalent, and Apple users will buy AirTags as usual.

Depending on how the future Google product will roll out, there is a good chance our DIYODE Tracker app will still have some application for use. We’re excited to see how BLE trackers and their wide-spread adoption onto new platforms will wow the tech world!


Visit for the project files.

Liam Davies

Liam Davies