I carry a 2nd gen iPod Mini as my main portable music player. There’s something really satisfying about listening to music through a dedicated handheld device, not having to worry about stream quality or bad network connection. (And that click wheel is something a touchscreen can never beat)
The issue with this, and an issue that most music listeners will face when wanting to do this, is that all the music I listen to is on Spotify. So how do I get all my Spotify music in an unencrypted format that can be transferred to a music player like an iPod?
I will walk you through the steps needed to do this and explain what I’ve distilled down to a very simple and quick workflow for syncing all of your Spotify playlists to an mp3 player of your choice.
Prerequisites
To get started, you’ll need 3 applications:
First, get the Spotify launcher installed and running, and make sure you’re logged in.
Install librespot-auth – when run, this is a script that will act as a spoof device for Spotify to connect to. It will mimic the likes of a speaker or other network device that Spotify is able to play music through. When you connect to this fake device, the script will capture your Spotify credentials during the handshake and save them into a plain text file that we will use later. These credentials are necessary for the other program, zotify, to access Spotify’s API and download music files directly from their source servers.
For arch users it is on the AUR
Install zotify – this is the main program that will be used to access Spotify’s API, download, and transcode your music files.
It is also on the AUR
Creating your credentials.json
Now that you have everything installed, go ahead and run librespot-auth:
librespot-auth --name "spoof device" --path "/home/yourUSER/.config/zotify/credentials.json
--name
= name of the fake device that will appear in Spotify
--path
= where the credentials file will be stored - use the path I’ve used above
--class
= this is optional and not necessary if you’re using a Premium Spotify account. For those that are using a free account, use --class=computer
. The default is speaker
but this does not work on free accounts.
Once run, you will be prompted to connect to the device in Spotify,

Then go ahead and connect to it,

Now if you go back to your terminal you should see a confirmation message,

Good, now that you have your credentials file saved, you no longer need the librespot-auth package, so you can go ahead and uninstall if you want to.
Fixing the credentials.json
Now, the credentials file as it stands is not formatted correctly. This is due to a recent change in how Spotify authenticates your credentials. We need to edit the credentials file slightly. I can’t show you mine, for obvious reasons, but this screenshot shows what you need to do:

The top section shows what your credentials.json should look like originally. You need to change it so that it looks like the bottom section.
The username line stays the same.
The “type” changes to “auth_type” and ‘1’ changes to “AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS”.
And “auth_data” changes to “credentials”.
Configuring zotify
Now that that is done, we need to change some settings in zotify’s config file. (/home/yourUSER/.config/zotify/config.ini)
This is what mine looks like:

Make sure your CREDENTIALS_LOCATION is the correct path to your credentials.json, and change the ROOT_PATH to where you want your music to be downloaded to. The other two important settings are DOWNLOAD_FORMAT and DOWNLOAD_QUALITY. I’ve chosen mp3 for format as that is the most compatible file format. Spotify stores music in .ogg files, so that is what you will get if you don’t specify the format. Make sure DOWNLOAD_QUALITY is set to “very high”. This will make the files download in their best quality, 320kbps bitrate. You can find more info about the different options on the zotify Github.
Download the music
Now that your credentials.json is saved and in the right format, and your zotify config is set up correctly. We can go ahead and start downloading our music.
Personally, I listen to all my music in playlists, and I believe this is the best way to download your Spotify library. There are many arguments and options to use in the zotify command, but for downloading your playlists, simply run:
zotify -p
Zotify will access Spotify’s API using your credentials and then display your playlists in a numbered list. Then all you need to do is choose which playlists to download based on their number. (eg; “1-5”, “1,3-6,10”, etc…)
Here’s a short video of me using the program:
You’ll notice a bunch of these files are showing as [SKIPPED] . This is because I’ve already downloaded the song previously. It will skip all existing songs until it finds new ones, which you will know when it starts to say “Preparing download” & “Converting file”. It will go through each playlist in order and then move on to the next.
Copy over the files
Now it’s as simple as copying your music onto your iPod or other mp3 player. My iPod currently has RockBox's custom firmware installed on it which I highly recommend. You don’t have to deal with iTunes anymore, all you need to do is simply drag and drop your music onto the device. If you don’t want to use a custom firmware, or have one of the unlucky iPod models with encrypted firmware, then I recommend using gtkpod. Currently, the Arch AUR package is not working due to a broken dependency, but a kind soul uploaded a version of it to the snap store, which I’ve tested and does work.
Conclusion
Going forward, all you need to do for further syncing is:
zotify -p
Plug in/mount your music player
cp -rnvp /src/of/music/. /ipod/music/folder
And thats it… Just two commands to fully download and sync your Spotify playlists to an iPod or any music player.
Explanation of common errors/warnings
You may run into messages such as “Couldn’t extract expiration. Invalid parameter in CDN”. This happened to me in the recording as well. This is most likely due to a parameter format change in Spotify’s CDN urls. Fortunately, it doesn’t matter too much for now, as the download will still initiate and complete or retry (you can increase retry attempts in the config). The program ran for about another 10 min in the recording above and every single new song was downloaded with no major errors.
If you get red errors like “COULDN’T FETCH METADATA” or something similar, this will actually result in a failed download. This is due to Spotify’s servers flagging your requests, due to the rate at which the songs are being downloaded. When you stream a song, it plays back in real time. When downloading through a program like this, it looks like your streaming songs way faster than normal because you’re downloading them at high speed and eventually this will flag your requests. If this happens, stop the program, and wait 15-20 min and then try again. You can also mess around with some of the other options in the config file – increasing “BULK_WAIT_TIME” and decreasing “CHUNK_SIZE” may help mitigate flagging.
Fortunately this doesn’t seem to occur until around 60-80 songs in during my testing, so it should only be a problem when you first download the bulk of your library. If you regularly keep up with downloading your playlists at a regular interval, you shouldn’t run into this issue ever again as you’ll only be downloading the handful of songs you’ve added since the last time.
Spotify’s API is volatile. They are regularly changing things in order to mitigate scraping. So you may run into other issues that are not listed here. Unfortunately, the official zotify dev branch does not get updated very often. There a several forks of zotify that have been been updated much more recently, here’s a couple: one & two. The official branch still works for me and that is why I chose to use it in this guide.