Playlists¶
Overview¶
Pushtunes can push playlists between any supported services — streaming services (Spotify, YouTube Music, Tidal) and local servers (Subsonic, Jellyfin) — without going through a separate CSV export step. Track-by-track matching uses similarity algorithms.
Basic Usage¶
# Between streaming services
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to ytm
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to tidal
pushtunes push playlist --from ytm --playlist-name "Synthwave Mix" --to spotify
# From streaming services to local servers
# Note: uses in-memory fuzzy matching against your entire music library
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to subsonic
pushtunes push playlist --from ytm --playlist-name "Chill Vibes" --to jellyfin
# From local servers to streaming services
pushtunes push playlist --from subsonic --playlist-name "My Mix" --to spotify
# Jellyfin requires --source-playlist-id (multiple playlists can have same name)
pushtunes push playlist --from jellyfin --source-playlist-id "8e5d6f1d17423354e83a3c17cae758dc" --to ytm
Finding Playlist IDs¶
Spotify:
When using Spotify as a source, you need the playlist ID:
1. Open the playlist in Spotify (desktop or web)
2. Click Share → Copy link to playlist
3. URL: https://open.spotify.com/playlist/37i9dQZF1DXaXB8fQg7xif
4. ID is the last part: 37i9dQZF1DXaXB8fQg7xif
Or use the Spotify URI: right-click playlist → Share → Copy Spotify URI → extract the part after playlist:.
Jellyfin:
- Open the playlist in Jellyfin web UI
- URL:
https://jellyfin.example.com/web/index.html#!/details?id=8e5d6f1d17423354e83a3c17cae758dc - ID is the value after
id=
Or via API: navigate to https://jellyfin.example.com/Users/{userId}/Items?IncludeItemTypes=Playlist and find the Id field.
TL;DR: Spotify and Jellyfin require --source-playlist-id (they allow duplicate names). YouTube Music works with either --playlist-name or --source-playlist-id.
Strict Matching with --require-all-tracks¶
By default, pushtunes creates a playlist even if some tracks can't be matched (partial success). For cross-service pushing, use strict mode:
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to ytm \
--require-all-tracks
In strict mode: - All tracks must be matched (automatically or via mappings) - If even one track can't be matched, the operation fails - No partial playlist is created - Fix failures with mappings and retry
Without strict mode (default): playlist is created with whatever tracks could be matched; missing tracks are skipped.
Handling Conflicts¶
When a playlist with the same name already exists on the target, use --on-conflict:
-
Displays: tracks in common, tracks to add, tracks to remove.abort(default): Show differences and exit without making changes -
replace: Replace the entire playlist with tracks from source -
append: Add only missing tracks to the existing playlist -
sync: Fully synchronize (add missing, remove extras, maintain order)
Using Target Playlist IDs¶
Spotify and Jellyfin allow duplicate playlist names. You can target a specific existing playlist using --playlist-id:
# First push creates the playlist — note the Playlist ID in output
pushtunes push playlist --from subsonic --playlist-name=argon --to spotify
# Output: Playlist ID: 59EkFxUZG0CnApHQIgYVUK
# Subsequent pushes using the ID
pushtunes push playlist --from subsonic --playlist-name=argon --to spotify \
--playlist-id=59EkFxUZG0CnApHQIgYVUK --on-conflict=sync
Same for Jellyfin:
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to jellyfin \
--playlist-id=8e5d6f1d17423354e83a3c17cae758dc --on-conflict=sync
You can find playlist IDs in the web player URL or from the previous push output.
Working with Mappings¶
When tracks can't be auto-matched (different names, remasters, etc.), use mappings to provide manual matches. See Mappings for full details and mappings_complete_example.csv for a template.
Step 1: Identify Failed Matches¶
Run with --report to see which tracks failed:
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to ytm \
--require-all-tracks \
--report=not_found,similarity_too_low
Note: The --export-csv option is only available for push albums and push tracks, not for playlists. Create your mappings file manually based on the report output.
Step 2: Fill in Mappings¶
For cross-service pushes, use the track-level columns:
type,artist,title,spotify_id,ytm_id,spotify_artist,spotify_title,ytm_artist,ytm_title,subsonic_artist,subsonic_title,subsonic_album,jellyfin_artist,jellyfin_title,jellyfin_album
track,"Volkor X","This Means War","","","","","Volkor X","This Really Means War",,,,,
track,"Mitch Murder","Current Events","","","","","Mitch Murder","Current Events (Remastered)",,,,,
For Subsonic/Jellyfin targets, use the subsonic_* and jellyfin_* columns:
type,artist,title,spotify_id,ytm_id,spotify_artist,spotify_title,ytm_artist,ytm_title,subsonic_artist,subsonic_title,subsonic_album,jellyfin_artist,jellyfin_title,jellyfin_album
track,"The Beatles","Let It Be",,,,,,,Beatles,Let It Be,Let It Be (Remastered),,,
track,"Foo Fighters","Best Of You",,,,,,,Foo Fighters,Best of You,Greatest Hits,,,
Step 3: Retry with Mappings¶
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to ytm \
--require-all-tracks \
--mappings-file=playlist_mappings.csv
Adjusting Similarity Threshold¶
If too many tracks aren't matching, try lowering the threshold:
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to ytm \
--similarity=0.7 \
--require-all-tracks
Default: 0.8 (80% similarity required). Range: 0.0 to 1.0. Lower thresholds may cause incorrect matches.
Verbose Output¶
Use -v or --verbose to see detailed track matching results:
pushtunes push playlist --from subsonic --playlist-name=jazz --to spotify -v
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to ytm \
--require-all-tracks \
--verbose \
--report=not_found,similarity_too_low
Example Workflows¶
Safe Cross-Service Migration¶
# Step 1: Try with strict mode, capture failures
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to ytm \
--require-all-tracks \
--report=not_found,similarity_too_low
# Step 2: Create a mappings file manually for failed tracks
# Step 3: Retry with mappings
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to ytm \
--require-all-tracks \
--mappings-file=playlist_mappings.csv
Bidirectional Sync¶
# Mirror Spotify playlist to YTM
pushtunes push playlist --from spotify --source-playlist-id "37i9dQZF1DXaXB8fQg7xif" --to ytm \
--on-conflict=sync
# Mirror YTM playlist to Spotify
pushtunes push playlist --from ytm --playlist-name "Favorites" --to spotify \
--on-conflict=sync
Limitations¶
- Track availability: Not all tracks available on one service exist on another
- Different versions: Services may have different versions (remaster, live, etc.)
- Metadata differences: Artist names and track titles may differ between services
- Rate limiting: Large playlists may take time due to API rate limits
Tips for Best Results¶
- Always use
--require-all-tracksfor cross-service pushing to ensure completeness - Use playlist IDs when possible for more reliable lookups
- Create mappings for problem tracks instead of lowering similarity threshold
- Test with small playlists first before migrating large collections
- Use
--verboseand--reportto understand matching behavior
Troubleshooting¶
"Playlist not found"
- Check playlist name spelling (case-insensitive but must match)
- Try using
--source-playlist-idinstead - Verify you're authenticated (check env vars for Spotify, browser.json for YTM)
"Only X/Y tracks matched"
- Use
--report=not_found,similarity_too_lowto see which tracks failed - Review the failures and create manual mappings
- Consider lowering
--similaritythreshold (but be careful)
"No tracks could be matched"
- Verify the target service has the music available
- Check if track/artist names are significantly different
- Use mappings to provide manual matches
See Also¶
- Getting Started - Authentication and basic setup
- Mappings - Manual track/album mappings for better matching
- Export-CSV.md - CSV export for retry workflows