Very often you come across a plain list of tracks of good songs, but with no playlist on Spotify, Apple Music or TIDAL etc is linked. For example I often see it on YouTube in the video description field. Often I like the songs so much I want to add it to a real playlist. I create a little script for this using the Spotify Web API.
Lets get started!
Create a Spotify application
- Head over to Spotify for Developers
- Create an App, give it a name and set a redirect URI for example
http://localhost:8080/callback
- Select “Web API” on the question “Which API/SDKs are you planning to use”?
- Click Save and copy your Client ID and Client Secret, you will need these in your a secrets file
.env
shortly.
Setup a project
- Initialize a new project using
npm init -y
- Install dependencies
npm i dotenv express spotify-web-api-node
- Create a
tracks.txt
with a song on each line for example:
Four Walls - Constellations
Randee Jean - You Got It
Cengiz - On On On
Don Pascal - Cape Verdean Bruk (Haze City Remix)
Future Disco - Future Disco Poolside 4 (DJ Mix)
28 Nathan Haines - Right Now (feat. Marlena Shaw)
- Create an
.env
file- Enter your client ID and secret like this
SPOTIFY_CLIENT_ID=XXX SPOTIFY_CLIENT_SECRET=XXX
- Define a few variables, port and playlist name
const PORT = 8080;
let playlistName = "";
- Now we instantiate the wrapper
const spotifyApi = new SpotifyWebApi({
clientId: process.env.SPOTIFY_CLIENT_ID,
clientSecret: process.env.SPOTIFY_CLIENT_SECRET,
redirectUri: "http://localhost:8080/callback",
});
- Define the request to the
/login
endpoint. The URL is used to initiate the authorization flow. We need to specify the scopes needed to define the access permissions the application requests from the user. We then redirect the user’s browser to the generated authorization URL. In my example I’m using three different scopes to be able to do what I want. Read more about Spotify Scopes here.
app.get("/login", (req, res) => {
const authorizeURL = spotifyApi.createAuthorizeURL(
["playlist-modify-public", "playlist-modify-private"],
"state"
);
res.redirect(authorizeURL);
});
- Define the request to the
/callback
endpoint. When the user will visit/login
it redirects to thehttp://localhost:8080/callback?code=AQDD61QPdOo)XXXXX
whereXXXXX
is the access token we need to use the Spotify Web API. If we are successful we proceed with the thecreatePlaylistAndAddTracks
.
app.get("/callback", async (req, res) => {
const { code } = req.query;
try {
const data = await spotifyApi.authorizationCodeGrant(code);
const { access_token, refresh_token } = data.body;
spotifyApi.setAccessToken(access_token);
spotifyApi.setRefreshToken(refresh_token);
console.log("✅ Successfully obtained access token: ", access_token);
res.send("✅ Authorization successful! You can now close this window.");
await createPlaylistAndAddTracks();
} catch (err) {
console.log("Error during authorization:", err);
res.send("Authorization failed. Please try again.");
}
});
- Define the
createPlaylistAndAddTracks
method. We read the contents of thetracks.txt
file and for each track we runsearchAndAddTrack
.
async function createPlaylistAndAddTracks() {
try {
const data = await spotifyApi.createPlaylist(playlistName, {
description: "A nice playlist",
public: false,
});
const playlistId = data.body.id;
const cleanedLines = await processTracksFile("tracks.txt");
await Promise.all(
cleanedLines.map((trackInfo) => searchAndAddTrack(trackInfo, playlistId))
);
console.log("All tracks added to playlist!");
process.exit();
} catch (err) {
console.log("Error creating playlist or adding tracks:", err);
}
}
- Now we define the
searchAndAddTrack
method which does a search on Spotify, if a result was found it adds it to the playlist using theaddTracksToPlaylist
method.
async function searchAndAddTrack(trackInfo, playlistId) {
try {
const [artist, song] = trackInfo.split(" - ");
const data = await spotifyApi.searchTracks(
`artist:${artist} track:${song}`,
{ limit: 1 }
);
const track = data.body.tracks.items[0];
if (track) {
const trackId = track.id;
console.log(`✅ Added track for song ${artist} - ${song}`);
await spotifyApi.addTracksToPlaylist(playlistId, [
`spotify:track:${trackId}`,
]);
} else {
console.log(`🚫 Track not found for ${artist} - ${song}`);
}
} catch (err) {
console.log("Error searching and adding track:", err);
}
}
- Start the Express application on port 8080
app.listen(PORT, () => {
process.stdout.write('\x1B[2J\x1B[0f'); // Just clear the shell
console.log(`Server is listening on port ${PORT}.`);
process.stdout.write(
"This tool will convert tracks from a text file to a Spotify playlist."
);
process.stdout.write("Give the playlist a name: ");
process.stdin.once("data", (data) => {
playlistName = data.toString().trim();
console.log(
"✅ Will create and add tracks to this playlist: ",
playlistName
);
console.log(
"\n\nNow Please open your browser and navigate to `http://localhost:8080/login` to authorize the application"
);
});
});
- Now the app is running
Server is listening on port 8080.
This tool will convert tracks in text file to a Spotify playlist
Give the playlist a name: Soulful House, Rare Grooves
✅ Will create and add tracks to this playlist: Soulful House, Rare Grooves
Now Please open your browser and navigate to http://localhost:8080/login to authorize the application
- The user visits
http://localhost:8080/login
and then the tracks are starting to add to the new playlist. Keep in mind, not all music is available on streaming platforms, so there’s a chance that some tracks may not be found.
✅ Successfully obtained access token: XXXXX
🚫 Track not found for Future Disco - Future Disco Poolside (DJ Mix
✅ Added track for song Nathan Haines - Right Now (feat. Marlena Shaw
✅ Added track for song Cengiz - On On On
✅ Added track for song Four Walls - Constellations
✅ Added track for song Randee Jean - You Got It
✅ Added track for song Don Pascal - Cape Verdean Bruk (Haze City Remix
🎷 Enjoy the music!