make your own spotify listening api
how to use a cloudflare worker to get your listening activity from spotify.
2022-11-03 (2 years ago)imported from my github gists
In this guide I will explain how to create a cloudflare worker that returns the current song you are listening to on spotify.
You may of seen my use of it on root of my site
Step 1: Get your Spotify client_id
, client_secret
and refresh_token
This great guide by Ben Wiz covers exactly this.
make sure you add the scopes
user-read-currently-playing
anduser-read-playback-position
Step 2: Set worker enviroment variables
Once you have the client_id
, client_secret
, and refresh_token
, set the enviroment variable REFRESH_TOKEN
with the value being the refresh_token
.
Additionally add the enviroment variable CLIENT_ENCODED
with the value of <client_id>:<client_secret>
base64 encoded.
make sure all you are base64 encoding is the
client_id
andclient_secret
seperated by a single colon!
Step 3: Setup cron trigger
The access_token
generated from the refresh token is only valid for an hour, so it needs to keep being refreshed. This will be done with a cron trigger.
Add a cron trigger to your cloudflare worker that runs every 30 minutes
or */30 * * * *
Step 4: Create a KV name space for the worker to use
The worker needs to hold onto the access_token
it generates every 30 minutes.
Create a KV Namespace with the name SPOTIFY
and add it to the KV Namespace bindings of your worker.
Located in the settings for your worker, below enviroment variables.
Step 5: Edit your cloudflare worker
Hit the Quick edit button on your cloudflare worker and paste in this:
addEventListener("fetch", (event) => {
event.respondWith(
handleRequest(event.request).catch((err) =>
JsonResponse({ error: err }),
),
);
});
addEventListener("scheduled", (event) => {
event.waitUntil(handleSchedule(event.scheduledTime));
});
async function handleSchedule(scheduledDate) {
await RefreshAccessToken();
}
async function handleRequest(request) {
const data = await NowPlaying();
return JsonResponse(data);
}
const REFRESH_URL =
"https://accounts.spotify.com/api/token?grant_type=refresh_token&refresh_token=";
const NOW_PLAYING_URL =
"https://api.spotify.com/v1/me/player/currently-playing";
const NO_DATA = {
artist: "",
artist_url: "",
url: "",
track: "",
image: "",
is_playing: false,
progress: 0,
track_length: 0,
ok: false,
};
function JsonResponse(data) {
return new Response(JSON.stringify(data), {
headers: {
"Access-Control-Allow-Origin": "*",
"content-type": "application/json;charset=UTF-8",
},
});
}
function ExtractData(json) {
try {
const {
progress_ms: progress = 0,
item: {
album: {
images: [{ url: image }],
},
artists: [
{
name: artist,
external_urls: { spotify: artist_url },
},
],
external_urls: { spotify: url },
duration_ms: track_length,
name: track,
},
is_playing,
} = json;
return {
artist,
artist_url,
url,
track,
image,
is_playing,
progress,
track_length,
ok: true,
};
} catch (_) {
return NO_DATA;
}
}
async function RefreshAccessToken() {
const resp = await fetch(REFRESH_URL + REFRESH_TOKEN, {
method: "POST",
headers: {
Authorization: `Basic ${CLIENT_ENCODED}`,
"Content-Type": "application/x-www-form-urlencoded",
},
});
const { access_token } = await resp.json();
await SPOTIFY.put("ACCESS_TOKEN", access_token);
return access_token;
}
async function NowPlaying() {
const ACCESS_TOKEN = await SPOTIFY.get("ACCESS_TOKEN");
const resp = await fetch(NOW_PLAYING_URL, {
method: "GET",
headers: {
Authorization: `Bearer ${ACCESS_TOKEN}`,
Accept: "application/json",
"Content-Type": "application/json",
},
});
// Status 204 - No Content success
if (!resp.ok || resp.status === 204) {
return NO_DATA;
}
const json = await resp.json();
return ExtractData(json);
}
Now make a request to your worker to make sure it works. The code is simple and you can modify/edit the code to better suite your needs.