Find My throws away the route. So I built the thing that keeps it A developer launched airtaghistory.com, a service that preserves AirTag location history that Apple's Find My discards, after a 69-day car shipment from Tacoma to Ljubljana left him with only the latest location per tag. The tool reads the owner's tags' rotating keys from the iCloud Keychain via a patched open-source library, decrypting location reports Apple cannot read, and stores each report in a database. The developer said the timestamped record let him prove a missed customs deadline was not his fault, and that the project was largely built with Claude Code. This week I launched airtaghistory.com https://airtaghistory.com . It keeps the AirTag location history that Apple’s Find My throws away. The LinkedIn post was the short version. This is the long one: the 69-day trip that made me build it, how it reads your tags’ locations without any help from Apple, the walls I hit, and what I learned building most of it with Claude Code between swims with my kids and kiteboarding. The 69 days When we moved from the US back to Slovenia https://gregakespret.substack.com/p/why-we-moved-back-to-slovenia-after , I shipped our car from Tacoma to Ljubljana. I handed the keys over at the port on 23 April 2026. One AirTag rode inside the car, one on the keys inside it, and one in each suitcase. I had a first version polling Find My before the ship left Tacoma. From then on, every location report landed in a database. That turned out to matter, because nobody I was paying could tell me much. On 4 June, I sent my freight forwarder coordinates showing the car’s AirTag on a residential street in Colón, Panama, three kilometres outside the port terminal. Their reply: they could only confirm what the carrier told them, and a claim could only be filed if the car never arrived. I was sure the car had been stolen. It hadn’t been. Someone had taken the tag out of the car and left it on that street. I only knew because the second tag, on the keys, kept moving with the shipment. Everything else I learned the same way, from my own map: - The shipment sat in Colón for 24 days. - It then called at four US ports before crossing the Atlantic. - The crossing took ten days, from 13 to 23 July, and produced two location updates in all that water. - It cleared Bremerhaven on 23 July. The driver bringing it south stopped overnight near Koblenz, which is how I knew to be outside my building on the 31st. The car arrived late on Friday afternoon, 31 July. That was also the deadline to close my T1 temporary-import paperwork, and the customs office had already shut for the weekend. The timestamped record showed exactly when the car arrived, so I could prove the missed deadline wasn’t my fault. Nothing was stolen and no claim was filed. But for 69 days, the only real information I had came from tags I owned and a database I’d written. Why Find My can’t show you where it’s been Find My keeps one location per AirTag: the latest. Each new report overwrites the last. That’s a deliberate privacy design. Location reports are end-to-end encrypted and Apple stores nothing it can read, so there’s no history on Apple’s side to hand over. That’s the right call for Apple. It’s a problem when your household is in a container and you need to know where it’s been, not just where it is. Before writing any code, I looked for something that already did this: - The Mac cache trick. Find My on macOS used to write tag locations to a local cache file, and a few open-source scripts read it every few minutes. macOS Tahoe locked that file down. - Screenshots. Possible, but nobody screenshots a map every ten minutes for two months. - Shortcuts. There’s no action that returns an AirTag’s coordinates. - An app that ranked for exactly this search. I signed up and found a landing page with no product behind it. Nothing worked for a consumer, so I built it. How it works An AirTag has no GPS and no cellular radio. It broadcasts a Bluetooth signal with a key that keeps rotating. When any iPhone passes nearby, the phone encrypts its own location with that key and uploads the report to Apple. Apple can’t read it. Only the owner’s private keys can decrypt it. So to read your own history, you need two things: 1. Your tags’ keys. They live in your iCloud Keychain, synced through CloudKit. I use a patched fork of an open-source library that joins the iCloud Keychain trust circle so it can read them. I fixed four bugs on the way: every tag resolved to the name “Unknown”, all my tags overwrote the same key file, it wrote dates Python couldn’t parse, and an OpenSSL update broke key unwrapping. 2. The encrypted reports. FindMy.py https://github.com/malmeloo/FindMy.py fetches the reports from Apple and decrypts them with those keys. A poller does this every 5 minutes for every connected account and writes latitude, longitude and timestamp to a database. Everything else is product around that loop: the map, the timeline, stop and dwell detection, reverse-geocoded place names, CSV and GPX export, the PDF evidence report, and billing. The stack is boring on purpose: Python and FastAPI, hosted on Railway, with Stripe Checkout for payments. One rule I set early: your Apple ID password is never stored. The library would quietly keep it inside the saved session if I let it, so I clear that field before anything is written. What’s stored is encrypted session tokens. When they expire, you reconnect. What Apple won’t let you do Most of what I learned was about limits. I put them on the site in plain words, because people trust “here’s what this can’t do” more than any feature list. - History starts when you connect. Nothing can reconstruct where a tag was before that. Connect before the truck arrives, not after. - The first connection takes two 2FA codes. I tried hard to cut it to one. Apple ties the sign-in chain to a single device identity, so a token from one sign-in won’t carry over to the other. I tried three ways to move it across, and all three failed. - Oceans are silent. Mid-ocean there are no iPhones to relay a sighting. The timeline shows that as a gap and doesn’t draw a line through it. A gap is data too. - It’s unofficial. Apple publishes no API for this, so I use the same Find My infrastructure your own devices use. Apple can break it any day. Upgrading FindMy.py once fixed an Apple sign-in outage that was returning 503 errors. Now I watch the sign-in success rate, not just uptime. - Things, not people. It only reads tags registered to the Apple ID you sign in with. The cryptography doesn’t allow anything else, and the acceptable-use policy forbids tracking people. Building it with Claude Code I had a second reason to build this. I wanted to learn agentic engineering by shipping something real, with real users, payments and a closed platform pushing back, not by reading threads about it. Most of it was built at the seaside in Croatia, in the gaps between swimming with my kids and kiteboarding. That only works because the agent does the typing. It never ran unattended, though. At first I reviewed almost every pull request. Over time I climbed the trust ladder and my reviews got lighter. In the meantime, I kept improving the harness around the agent: skills, gates, and James Davis’s Model-Based Agentic Engineering https://davisjam.github.io/model-based-agentic-software-engineering/ MAGE . MAGE makes the important knowledge explicit as models, and checks that the requirements actually shape the work. Three moments taught me the most. 1. Start with a goal the agent can check itself against. The very first task wasn’t “build an AirTag tracker”. It was: get the location of these four AirTags, by name, and compare the result with what Find My shows on my Mac right now. Look at existing libraries in any language, and actually run the code instead of describing it. A real, named target gave the agent a way to know when it was done, and gave me a way to know it wasn’t bluffing. 2. One invented fact can cost you more than one line. Claude Code once opened a pull request that updated the README with a setup command using a --db flag. I didn’t recognise the flag, so I asked. It checked the source and admitted it had invented it. That was the small problem. Earlier in the same session, it had deleted the migration script, the only code that loaded the database, because it reasoned the new flag made that script redundant. One made-up fact, two changes built on top of it, and I caught it only because I was curious. Catching that shouldn’t depend on curiosity. Now commands in the docs get run, not just read: check flags against --help , and run README steps in CI. I first told this story on LinkedIn https://www.linkedin.com/feed/update/urn:li:activity:7477753102448726016/ . A quieter version followed: Claude Code insisted a feature was impossible while my own repo already did it. I wrote that one up here https://gregakespret.substack.com/p/claude-code-kept-telling-me-a-feature . 3. The agent writes copy as confidently as it writes code. I asked for an FAQ entry explaining why my site can show a more recent location than Find My. The draft credited it to querying a wider window of rotating keys. It sounded technical and plausible, and it was wrong. The real reason is simpler: the site polls every 5 minutes and keeps every report. I only found the error because I asked it to recheck its claims against the code and the live site. For anything customers read, that recheck is a step in the process, not a hope. The pattern across all three: the agent made code cheap. It didn’t make judgment cheaper. Knowing what Apple won’t allow, which claim is true, and which deleted file mattered was still my job. I wrote more about that shift, and the log-auditing loop I set up to catch what reviews miss, in What we lose when we stop writing code https://gregakespret.substack.com/p/what-we-lose-when-we-stop-writing . Pricing for an episode, not a subscription Most people don’t need tracking forever. They need it for one move, one trip or one claim. So the main products are one-time passes: The mental model is a Carfax report. People pay about $45 for one before buying a used car, once, because the stakes are high and the information isn’t available anywhere else. A move is the same kind of moment. The average US move costs about $3,000, and by default a mover owes you 60 cents per pound if something goes missing. Two rules sit on top of the prices. Whatever gets recorded stays visible and exportable forever, paid or not. And if the service doesn’t capture a usable route for your move, you get a full refund and keep the report. Try it If you have an AirTag on your keys, in a bag, or in a box that’s about to ship, try it at airtaghistory.com https://airtaghistory.com . The first 7 days are free, no card needed, with unlimited AirTags. Connect before it leaves. History starts the moment you connect. I’d love to hear what you’d use it for, and what breaks. Reply to this email or leave a comment. And if you know someone who’s about to move, forward this to them.