Skip to content

Instantly share code, notes, and snippets.

Created February 3, 2022 06:06
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Getting a Spotify refresh_token
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OAuth | Spotify</title>
<h1>Local OAuth for Spotify</h1>
<button id="btn">Authorize</button>
<script type="module">
// Setup your client_id and client_secret!
const clientId = "TODO"
const clientSecret = "TODO"
const redirectUri = "http://localhost:8080"
// if the code is available...
const currentUrl = new URL(document.location)
if (currentUrl.searchParams.get('code')) {
// we have the code!
const code = currentUrl.searchParams.get('code')
const state = currentUrl.searchParams.get('state')
if (localStorage.getItem("state") !== state) {
console.warn("State does not match! Your authorization might be outdated or tampered.")
const body = [
["code", code],
["redirect_uri", redirectUri],
["grant_type", "authorization_code"]
].map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
fetch("", {
headers: {
"Authorization": `Basic ${btoa(`${clientId}:${clientSecret}`)}`,
"Content-Type": "application/x-www-form-urlencoded"
method: "POST"
}).then(x => x.json()).then(
x => {
if (x.error) {
alert(`Error: ${x.error}\nRemove "code=" from the URL and retry.`)
console.log("Your (temporary) access_token:", x.access_token)
console.log("Your refresh_token:", x.refresh_token)
alert(`Authorization done! Check the console to see the details.\nYour refresh_token is: ${x.refresh_token}`)
// if the code is not available..
document.querySelector("#btn").addEventListener("click", (e) => {
// random string
const state = String(Math.random()) + String(Math.random())
localStorage.setItem("state", state)
// user-top-read: needed for Top Tracks
// user-library-read: needed for Saved Tracks
const scope = "user-top-read user-library-read"
const url = new URL("")
for (const [key, value] of [
["response_type", "code"],
["client_id", clientId],
["scope", scope],
["redirect_uri", redirectUri],
["state", state]
]) {
url.searchParams.set(key, value)
document.location = String(url)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment