Skip to content
Announcement:We are updating the criteria to be granted extended access to the Web API.
Please note that starting May 15, 2025 we’re introducing some changes to the way we provide Web API extended quota mode access. For more information, read here.

Refreshing tokens

A refresh token is a security credential that allows client applications to obtain new access tokens without requiring users to reauthorize the application.

Access tokens are intentionally configured to have a limited lifespan (1 hour), at the end of which, new tokens can be obtained by providing the original refresh token acquired during the authorization token request response:


_10
{
_10
"access_token": "NgCXRK...MzYjw",
_10
"token_type": "Bearer",
_10
"scope": "user-read-private user-read-email",
_10
"expires_in": 3600,
_10
"refresh_token": "NgAagA...Um_SHo"
_10
}

Request

To refresh an access token, we must send a POST request with the following parameters:

Body ParameterRelevanceValue
grant_typeRequiredSet it to refresh_token.
refresh_tokenRequiredThe refresh token returned from the authorization token request.
client_idOnly required for the PKCE extensionThe client ID for your app, available from the developer dashboard.

And the following headers:

Header ParameterRelevanceValue
Content-TypeRequiredAlways set to application/x-www-form-urlencoded.
AuthorizationOnly required for the Authorization CodeBase 64 encoded string that contains the client ID and client secret key. The field must have the format: Authorization: Basic <base64 encoded client_id:client_secret>

Example

The following code snippets represent two examples:

browser
nodeJS

_25
const getRefreshToken = async () => {
_25
_25
// refresh token that has been previously stored
_25
const refreshToken = localStorage.getItem('refresh_token');
_25
const url = "https://accounts.spotify.com/api/token";
_25
_25
const payload = {
_25
method: 'POST',
_25
headers: {
_25
'Content-Type': 'application/x-www-form-urlencoded'
_25
},
_25
body: new URLSearchParams({
_25
grant_type: 'refresh_token',
_25
refresh_token: refreshToken,
_25
client_id: clientId
_25
}),
_25
}
_25
const body = await fetch(url, payload);
_25
const response = await body.json();
_25
_25
localStorage.setItem('access_token', response.access_token);
_25
if (response.refresh_token) {
_25
localStorage.setItem('refresh_token', response.refresh_token);
_25
}
_25
}

Response

If everything goes well, you'll receive a 200 OK response which is very similar to the response when issuing an access token:


_10
{
_10
access_token: 'BQBLuPRYBQ...BP8stIv5xr-Iwaf4l8eg',
_10
token_type: 'Bearer',
_10
expires_in: 3600,
_10
refresh_token: 'AQAQfyEFmJJuCvAFh...cG_m-2KTgNDaDMQqjrOa3',
_10
scope: 'user-read-email user-read-private'
_10
}

The refresh token contained in the response, can be used to request new tokens. Depending on the grant used to get the initial refresh token, a refresh token might not be included in each response. When a refresh token is not returned, continue using the existing token.