Sync your Last.fm play counts and loved tracks to Navidrome with intelligent caching.
-
Install dependencies:
git clone https://github.com/zeroquinc/NaviSync.git cd NaviSync pip install -r requirements.txt -
Configure: Copy
env.exampleto.envand fill in your details:NAVIDROME_DB_PATH=Z:/navidrome/navidrome.db NAVIDROME_URL=http://192.168.0.50:4533 LASTFM_API_KEY=lastfmapikey LASTFM_USER=Username SCROBBLED_FIRSTARTISTONLY=True FIRST_ARTIST_WHITELIST=["Suzan & Freek", "Simon & Garfunkel", "AC/DC"] ENABLE_FUZZY_MATCHING=True PLAYCOUNT_CONFLICT_RESOLUTION=ask SYNC_LOVED_TO_LASTFM=False ALBUM_MATCHING_MODE=album_agnostic
-
Run:
python main.py -
It is important to delete the cache and json folders when updating from this repo, as they may contain some changes.
- Keep your play counts in sync - Never lose track of your listening history by updating Navidrome play counts
- Sync your loved tracks - Last.fm hearts become Navidrome stars
- Reverse sync (optional) - Sync Navidrome stars TO Last.fm as loved tracks (requires authentication)
- Fast after first run - Only processes new plays, not your entire history
- Intelligent fuzzy matching - Finds potential matches for track name variations:
- Handles
&vsand, special characters, accents, and minor differences - Always prompts you to confirm - no automatic matching to prevent errors
- Shows similarity scores to help you decide
- Remembers your choices - confirmed matches are saved and used automatically in future runs
- You have full control over which tracks get matched
- Handles
# Extract first artist from collaborations (e.g. "Artist A feat. Artist B" → "Artist A")
SCROBBLED_FIRSTARTISTONLY=True
FIRST_ARTIST_WHITELIST=["Simon & Garfunkel", "AC/DC"] # Keep these exactENABLE_FUZZY_MATCHING=True # Default: TrueOptions:
True- Enable fuzzy matching with prompts for similar tracks (recommended for accuracy)False- Only exact matches, no prompts (faster but fewer matches)
When enabled, the script intelligently finds potential matches for track name variations and prompts you to confirm. When disabled, only 100% exact matches are synced.
PLAYCOUNT_CONFLICT_RESOLUTION=ask # Options: ask, navidrome, lastfm, higher, incrementConflict Options:
ask- Prompt for each conflict (default)navidrome- Keep Navidrome when higherlastfm- Always use Last.fmhigher- Use whichever is higherincrement- Add counts together
ALBUM_MATCHING_MODE=album_agnostic # Options: album_agnostic, album_aware, promptAlbum Handling Options:
album_agnostic- Combine scrobbles for same artist/title regardless of album (default, current behavior)- Example: "Track A" on "Album X" and "Compilation Y" both get 100 plays total from Last.fm
- When multiple album versions exist, prompts user to choose which to update
album_aware- Match by artist/title/album, allowing different play counts per album- Example: "Track A" on "Album X" gets 60 plays, same track on "Compilation Y" gets 40 plays
- Ideal for mixed albums, compilations, and avoiding duplicate play counts in smart playlists
prompt- Like album_agnostic, but always asks which album version(s) to update (no auto-selection)
Sync Navidrome starred tracks TO Last.fm as loved tracks:
SYNC_LOVED_TO_LASTFM=True # Default: FalseSetup (one-time):
-
Get your API Secret from Last.fm API Account
-
Add to
.env:LASTFM_API_SECRET=yourapisecret
-
Get session key (interactive):
python -c "from src.lastfm import get_session_key; get_session_key()" -
Follow the prompts, authorize in browser, then add the session key to
.env:LASTFM_SESSION_KEY=yoursessionkey
-
Enable reverse sync:
SYNC_LOVED_TO_LASTFM=True
View cache status: python cache_info.py --info
View fuzzy match mappings: python cache_info.py --fuzzy
Reset sync status: python cache_info.py --reset
Fuzzy Match Mappings: Once you confirm a fuzzy match (e.g., "The Great Hall and The Prophecy" → "The Great Hall & The Prophecy"), it's saved in the cache. Future runs will automatically use this mapping without prompting you again.
Setup issues: python check_setup.py
First run slow: Normal - fetches all historical scrobbles. Subsequent runs are fast!
MIT License - see LICENSE file for details.