First, we need to create a Spotify application to give us credentials to authenticate with the API. The Spotify Web-API is free to use, but you need to have a spotify premium account to access all functionalities.
http://localhost:3000
or any other URL as a redirect URI.All done! You now have a properly configured Spotify application and the correct credentials to make requests.
There are a view different ways to authenticate with the Spotify API. We will use the Authentication Code Flow.
First, we need an authorizatiion code, where we need to specify, what information about we will get access to. Make a GET request to the following endpoint:
https://accounts.spotify.com/authorize?client_id=<your_id>&response_type=code&redirect_uri=http://localhost:3000&scope=user-read-currently-playing user-modify-playback-state
For the redirect URI you can put any url that you have registered at the spoify dashboard in step 1. As the scope, you can put any scope you will need for you project to work. Here, we just need ‘user-read-currently-playing’.
After authorizing, you’ll be redirected back to your redirect_uri
. In the URL, there’s a code
query parameter. Save this value.
http://localhost:3000/callback?code=NApCCg..BkWtQ
Next, you need to retrieve the refresh token. You need to make a POST request like this.
curl -H 'Authorization: Basic <base64 encoded client_id:client_secret>' -d grant_type=authorization_code -d code=<code> -d redirect_uri=http://localhost:3000 https://accounts.spotify.com/api/token
You can e.g. make this request with javascript like this:
const getRefreshToken = await fetch('https://accounts.spotify.com/api/token', {
method: "POST",
headers: {
Authorization: `Basic ${Buffer.from(`${client_id}:${client_secret}`).toString('base64')}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: <code from the previous step>,
redirect_uri: "http://localhost:3000"
})
});
console.log(await getRefreshToken.json());
This will return a JSON response containing a refresh_token
.
To securely store the tokens and keys for the API, we create an .env.local
file at the root of the project and store the client_id
, client_secret
and the refresh_token
there. You can access the environment variables in code like this: process.env.<ENV_NAME>
const basic = Buffer.from(`${<client_id>}:${<client_secret>}`).toString('base64');
const TOKEN_ENDPOINT = `https://accounts.spotify.com/api/token`;
const getAccessToken = async () => {
const response = await fetch(TOKEN_ENDPOINT, {
method: "POST",
headers: {
Authorization: `Basic ${basic}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: <refresh_token>
})
})
return response.json();
}
With this access token, we have access to the Spotify Web-API. We can e.g. get the song, the user of the client_id
is listening to:
const NOW_PLAYING_ENDPOINT = `https://api.spotify.com/v1/me/player/currently-playing`;
export const getNowPlaying = async () => {
const { access_token } = await getAccessToken();
return fetch(NOW_PLAYING_ENDPOINT, {
method: "GET",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
});
};
This method can be called by e.g. a next.js api function like this:
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const response = await getNowPlaying();
// 204: No data available, >= 400: error
if (response.status === 204 || response.status > 400) {
return res.status(200).json({ isPlaying: false });
}
const song = await response.json();
if (song.item === null) {
return res.status(200).json({ isPlaying: false });
}
const title = song.item.name;
const artist = song.item.artists
.map((_artist: any) => _artist.name)
.join(", ");
return res.status(200).json({
artist,
title,
});
}