Spotify has Wrapped. Apple Music has Replay. But what about iTunes and iPod users?
TunesBack brings year-end analytics to your local music library. Track your listening habits, see your top artists, albums and songs, and discover how your taste evolves over time.
Works with iTunes and Apple Music libraries on Windows, macOS, and Linux.
Powered by libpytunes for iTunes XML parsing.
- Compare periods or analyze single snapshots (XML files must be properly named: see guide below)
- Top Artists, Albums & Songs with customizable rankings (5–100 items)
- Sort with Genres, New Finds, Skipped Tracks & Years
- Album art displayed alongside track details
- Network share support: seamlessly works with UNC paths (Windows) and GVFS/CIFS mounts (Linux)
- Wrapped cards: shareable Spotify-style visual summaries
- Listening Age: calculates the "era" of music you gravitate toward
- Flexible display: switch between hours/minutes, sort by time or plays
- Dark and light mode
- Fully offline: all processing happens on your machine
Generate shareable images summarizing your listening habits.
Available cards:
- Top Songs & Albums: ranked lists with album artwork
- Top Genres: typographic genre tiles
- Top Song: hero card with large cover art
- Minutes Listened: total listening time
- Listening Age: your calculated musical age
- Summary: overview combining top artist, stats, and genres
The order of items follows the "Ranked By" setting. Re-generate after changing the ranking.
More card types to come!
TunesBack computes a single-number summary called the "Listening Age" to describe the era that most strongly characterizes your listening habits. The metric is inspired by the psychological "reminiscence bump", which is the tendency for music encountered during one's formative years to retain stronger emotional significance.
The following chart explains its methodology:
- Aggregate play counts by each track's release year.
- Slide a 5-year window across the years in your data and compute the total plays for each window.
- Select the 5-year window with the highest total plays (the "peak era").
- Take the center year of that window and assume the listener was 18 at that midpoint.
- Calculate Listening Age as: current year − (midpoint year − 18).
Formula:
Listening Age = Current Year - (Peak Era Midpoint - 18)
Example:
- Peak window: 2010–2014 → midpoint 2012
- Assumed birth year: 2012 − 18 = 1994
- Listening Age (in 2025): 2025 − 1994 = 31
Notes and interpretation:
- A Listening Age lower than your chronological age indicates a preference for more recent releases.
- A Listening Age higher than your chronological age indicates a preference for older material.
- The method uses a fixed 5-year window and a formative age constant of 18; these parameters reflect a balance between sensitivity and robustness in typical music libraries.
Implementation details: the algorithm (see listening_age_algorithm.py) filters out invalid years, sums plays per year, evaluates every 5-year window, selects the highest-sum window, and computes the final age as shown above.
TunesBack uses a multi-stage validation process to accurately identify genuinely new additions to your library, distinguishing them from tracks whose metadata has been edited and pre-existing tracks that were simply unplayed.
When comparing two library snapshots, a track qualifies as a New Find only if all of the following conditions are met:
- Play Count Increase: The track shows increased play activity (
diff_count > 0) in the more recent snapshot. - No Persistent ID Match: The track's unique identifier (Persistent ID) does not exist in the baseline library, this confirms it wasn't already present.
- Date Added Verification (comparison mode): If a baseline date exists, the track's
Date Addedtimestamp must fall after that date.
When analyzing a single library export (no baseline for comparison), a track is classified as a "New Find" if:
- It has at least one play (
count > 0) - No matching Persistent ID exists from a previous reference (i.e., no prior play history)
iTunes assigns each track a unique Persistent ID that remains constant even if the file is renamed, moved, or re-tagged. By checking for ID matches between snapshots, TunesBack can:
- Detect tracks whose metadata has been edited
- Avoid false positives from tracks that existed but were never played
- Accurately track genuinely new library additions
flowchart TD
A[Track in New Snapshot] --> B{Play count<br/>increased?}
B -->|No| X[❌ Not a New Find]
B -->|Yes| C{Comparison mode<br/>AND has Date Added?}
C -->|Yes| D{Date Added ><br/>baseline date?}
C -->|No| E{Old play count<br/>== 0?}
D -->|No| X
D -->|Yes| F{Persistent ID<br/>exists in old library?}
E -->|No| X
E -->|Yes| F
F -->|Yes| X
F -->|No| Y[✅ New Find]
IF play_count_increased THEN
IF comparison_mode AND has_date_added THEN
new_find = (date_added > baseline_date) AND (no_persistent_id_match)
ELSE
new_find = (old_play_count == 0) AND (no_persistent_id_match)
Implementation details: see the calculate_diff() and process_stats() methods in main.py.
TunesBack extracts album artwork directly from your audio files using embedded metadata tags and features intelligent path resolution for network shares. This ensures artwork displays even when files are stored on remote servers or have been moved.
- Direct extraction: Uses Mutagen to read embedded artwork from audio file tags (ID3, MP4, FLAC, etc.)
- Smart path resolution for network shares: Automatically handles:
- Windows UNC paths: Converts
file://server/share/...to\\server\share\... - Linux GNOME/GVFS: Auto-detects mounts at
/run/user/<uid>/gvfs/smb-share:... - Linux KDE/kio-fuse: Auto-detects Dolphin mounts at
/run/user/<uid>/kio-fuse-*/smb/... - macOS network volumes: Resolves
/Volumes/...paths - Hostname ↔ IP resolution: Works even when XML uses hostname but mount uses IP
- Moved files: Works as long as the new path is accessible
- Windows UNC paths: Converts
- No configuration needed: Network paths are resolved automatically across all platforms
If album art doesn't appear:
- Enable Debug Logging in the app settings
- Check the log file for path resolution errors:
- macOS:
~/Library/Logs/TunesBack/tunesback.log - Windows:
%LOCALAPPDATA%\TunesBack\Logs\tunesback.log - Linux:
~/.cache/TunesBack/logs/tunesback.log
- macOS:
- Verify your audio files have embedded artwork:
# macOS/Linux ffprobe -v error -show_entries format_tags=title -of default=noprint_wrappers=1 "song.mp3" # Or use any audio tagger to check
- For network shares, ensure they're mounted before starting TunesBack
Windows:
- Map network drive or use UNC paths directly
- XML paths like
file://server/share/Music/...are automatically converted
Linux:
- KDE/Dolphin: Simply browse to the network share in Dolphin before launching TunesBack
- GNOME/Nautilus: Connect via Files → Other Locations → Connect to Server
- Manual mount:
sudo mount -t cifs //server/share /mnt/music -o username=user
Download from Releases
| Platform | Format |
|---|---|
| Windows | Installer (.exe) |
| macOS | Disk image (.dmg) |
macOS: You may need to go to System Settings → Privacy & Security and click "Open Anyway" the first time.
Linux users should run from source:
git clone https://github.com/mooseses/TunesBack.git
cd TunesBack
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python main.pyRequirements: Python 3.10+
Or run from source on any platform:
git clone https://github.com/mooseses/TunesBack.git
cd TunesBack
pip install -r requirements.txt
python main.py- In iTunes or Music, go to File → Library → Export Library
- Save the file with a date in the name (e.g.,
2025-12-01.xml) - Export again later to compare snapshots
- Click Select Folder and point to your XML files
- Choose a date range or a single snapshot
- Click Generate Recap
- Use the pencil icon to show or hide tabs
- Click Generate Wrapped to create shareable cards
TunesBack extracts dates from filenames automatically. It displays them as YYYY-MM-DD in the app.
2025-12-01.xml
2025_12_01.xml
December-01-2025.xml
Dec-01-2025.xml
01 December 2025.xml
2025-12-01 iTunes Library.xml
Library_2025_12_01_backup.xml
Use ISO format (YYYY-MM-DD.xml) or include the month name to avoid ambiguity.
library.xml: no datev2.1.3-export.xml: version numbers get confused with datesbackup.xml: no date01-12-2025.xml: could be January 12 or December 112-01-2025.xml: same issue
You can schedule a task to copy your library XML to a snapshots folder:
macOS/Linux (cron):
# Monthly on the 1st at midnight
0 0 1 * * cp ~/Music/iTunes/iTunes\ Library.xml ~/Music/Snapshots/$(date +\%Y-\%m-\%d).xmlWindows (PowerShell via Task Scheduler):
$date = Get-Date -Format "yyyy-MM-dd"
Copy-Item "$env:USERPROFILE\Music\iTunes\iTunes Library.xml" "$env:USERPROFILE\Music\Snapshots\$date.xml"- Album art is extracted from embedded tags. iTunes' "Get Album Art" feature stores artwork separately and won't be picked up.
- Moved libraries: if your music files have moved and the XML paths are outdated, artwork won't load. Enable debug logging to investigate.
- Network shares: path resolution works best when shares are already mounted.
- CJK text: font fallback for Asian characters in Wrapped cards is limited.
Enable "Debug Logging" in the app to see why artwork might be missing.
- Flet: Python UI framework
- libpytunes: iTunes XML parser
- pandas: data analysis
- Pillow: image generation
- mutagen: audio metadata extraction
- python-dateutil: date parsing
Found a bug or have a suggestion? Open an issue.
GPL-3.0. See LICENSE for details.









