January 14, 2026/908 words/5 min read
Apple Music Won't Let Me Remember
Last.fm doesn't work, Apple doesn't care.
I really like knowing what I listen to. The data-obsessed, Spotify Wrapped, share-your-personality-as-a-pie-chart stuff does nothing for me. I want to look back at a month and remember that I played the same album fourteen times during a rough week at work, or that I discovered a band on an evening in November and did not stop listening to them until March. My listening history marks periods of my life in a way calendars don't, and I want a nice record of that.
Apple Music does not want me to have this. There's no native scrobbling, no listening history export, nothing that says "here's what this guy played". The closest thing is the official dev API. I already have a developer account, the keys take five minutes to set up, and it would have worked on the first try. I refused to use it. Pointing Apple's own sanctioned pipeline at my listening felt like asking them for permission to keep something that should have been mine to begin with, so I wanted to build my own thing instead. There's also the Recently Played shelf in the app, but it holds maybe fifty items before it starts forgetting and groups by album rather than individual plays. You can't query or export it, and you can't scroll back far enough to see what you were listening to two weeks ago.
Last.fm was the next obvious answer. I used it on and off between 2008 and 2015. The problem is that the Apple Music integration is, and has been for years, broken in the cursed way that makes you think it almost works. Scrobbles appear sometimes, other times they don't, and occasionally a song shows up three hours late. I've seen an entire album vanish from my scrobble list. Background playback is unreliable, CarPlay scrobbles are a coin flip, and if your phone locks at the wrong moment the whole thing gives up without showing you a single error. If I spend more time in an evening debugging whether my listening data was accurate than listening to music, something has gone very wrong.
The Last.fm app on iOS relies on the MPNowPlayingInfoCenter API, which Apple exposes but doesn't seem to prioritise for third-party use. Spotify works more reliably because it handles its own scrobbling server-side. Apple Music doesn't, leaving Last.fm dependent on system-level hooks that have been flaky in my experience.
So I built my own ugly thing, and it mostly works.
The core idea is simple. Apple Music on macOS exposes the current track through ScriptingBridge. I wrote a small daemon in Swift that polls the player state every few seconds, deduplicates repeated events, and logs each play to a local SQLite database. It runs on both my devices and catches everything I play at my desk.
import ScriptingBridge
@objc protocol MusicApplication {
@objc optional var currentTrack: MusicTrack { get }
@objc optional var playerState: Int { get }
}
@objc protocol MusicTrack {
@objc optional var name: String { get }
@objc optional var artist: String { get }
@objc optional var album: String { get }
@objc optional var duration: Double { get }
}
func pollCurrentTrack() -> ScrobbleEntry? {
guard let app = SBApplication(bundleIdentifier: "com.apple.Music") as? MusicApplication,
let track = app.currentTrack,
let state = app.playerState,
state == 0x6B505353 // kMusicPlayerStatePlaying
else { return nil }
return ScrobbleEntry(
artist: track.artist ?? "Unknown",
album: track.album ?? "Unknown",
title: track.name ?? "Unknown",
duration: track.duration ?? 0,
timestamp: Date()
)
}For mobile plays, where most of my listening happens, I use a Shortcut automation that fires when the Music app opens and logs the current track info to a JSON file in iCloud Drive. It's incredibly clunky. It misses tracks if I skip too fast and straight up doesn't catch songs played through CarPlay. But it captures maybe eighty percent of my phone listening, which is more than I had before.
The daemon picks up the iCloud JSON files, deduplicates against what it already has, and merges everything into the same SQLite database. The schema is intentionally boring.
CREATE TABLE scrobbles (
id INTEGER PRIMARY KEY,
artist TEXT NOT NULL,
album TEXT,
title TEXT NOT NULL,
duration_seconds INTEGER,
played_at TIMESTAMP NOT NULL,
source TEXT DEFAULT 'macos',
UNIQUE(artist, title, played_at)
);
CREATE INDEX idx_played_at ON scrobbles(played_at);
CREATE INDEX idx_artist ON scrobbles(artist);I built a tiny web UI with Next.js to browse it, a basic timeline view, a top artists breakdown by week and month, and a search. It runs locally on the homelab Mac mini, and I can access it over Tailscale when I'm out. Having a personal dashboard for something this niche scratches my nerdy itch, and it loads instantly because it's my data in a SQLite file.
The whole setup has been running for about two months now. I can already look back at December and see the shape of it. A lot of Stevie Wonder during the first week, then a sudden Rachmaninoff phase that lasted ten days, then a stretch of 80s Pop while shipping a feature at work. That's exactly what I want! I don't care much about analytics or insights, but the data is there if that changes.
Building all this was unreasonable. A proper native listening history or a reliable Last.fm integration would have made it unnecessary. Instead, I chose a hack over Apple's developer API, so here we are.
For a while, it worked well enough, and the data was mine.
Update, June 2026. Yeah, I just gave up.
The eighty percent kept bugging me. There were too many gaps where a CarPlay drive or a morning of phone listening should've been.
I ended up using the API, the exact thing I swore off at the top of this post and could have done on day one. It was never the effort. I didn't want to reward Apple's stubbornness, so I rewarded mine instead and babysat the hack. Eventually the gaps became more annoying than my pride, and I caved. You sign a developer token with a .p8 key, grab a Music User Token, and make the request below.
curl "https://api.music.apple.com/v1/me/recent/played/tracks" \
-H "Authorization: Bearer $DEVELOPER_TOKEN" \
-H "Music-User-Token: $USER_TOKEN"That returns clean JSON for every device, CarPlay included. I poll it from the homelab into the same SQLite table, so the UI didn't change, and the Swift daemon and Shortcut are gone. The token expires every six months and I'll forget until the dashboard goes quiet, but it works now.