A Node.js wrapper for Spotify's Web API
This is a Node.js wrapper/client for the Spotify Web API. If you want to make requests directly from the browser, please check out spotify-web-api-js. A list of selected wrappers for different languages and environments is available at the Developer site's Libraries page.
It includes helper functions to do the following:
- Albums, artists, and tracks
- Albums for a specific artist
- Top tracks for a specific artist
- Artists similar to a specific artist
- User's emails, product type, display name, birthdate, image
- Albums, artists, tracks, and playlists
- Get a user's playlists
- Create playlists
- Change playlist details
- Add tracks to a playlist
- Remove tracks from a playlist
- Replace tracks in a playlist
- Reorder tracks in a playlist
- Add, remove, and get tracks that are in the signed in user's Your Music library
- Check if a track is in the signed in user's Your Music library
- Get New Releases
- Get Featured Playlists
- Get a List of Categories
- Get a Category
- Get a Category's Playlists
- Follow and unfollow users
- Follow and unfollow artists
- Check if the logged in user follows a user or artist
- Follow a playlist
- Unfollow a playlist
- Check if users are following a Playlist
Some methods require authentication, which can be done using these flows:
Even though authentication isn't always necessary, it always gives benefits such as an increased rate limit.
$ npm install spotify-web-api-node --save
First, instantiate the wrapper.
var SpotifyWebApi = require'spotify-web-api-node';// credentials are optionalvar spotifyApi =clientId : 'fcecfc72172e4cd267473117a17cbd4d'clientSecret : 'a6338157c9bb5ac9c71924cb2940e1a7'redirectUri : '';
If you've got an access token and want to use it for all calls, simply use the api object's set method. Handling credentials is described in detail in the Authorization section.
Lastly, use the wrapper's helper methods to make the request to Spotify's Web API. The wrapper uses promises, so you need to provide a success callback as well as an error callback.
// Get Elvis' albumsspotifyApigetArtistAlbums'43ZHCT0cAZBISjO8DG9PnE'thenconsole.log'Artist albums' databody;console.errorerr;;
If you dont wan't to use promises, you can provide a callback method instead.
// Get Elvis' albumsspotifyApigetArtistAlbums'43ZHCT0cAZBISjO8DG9PnE'if errconsole.error'Something went wrong!';elseconsole.logdatabody;;
The functions that fetch data from the API also support an optional JSON object with a set of options. For example, limit and offset can be used in functions that returns paginated results, such as search and retrieving an artist's albums.
// Passing a callback - get Elvis' albums in range [20...29]spotifyApigetArtistAlbums'43ZHCT0cAZBISjO8DG9PnE' limit: 10 offset: 20thenconsole.log'Album information' databody;console.errorerr;;
To enable caching, this wrapper now exposes the response headers and not just the response body. Since version 2.0.0, the response object has the format
In previous versions, the response object was the same as the response body.
Retrieving a track's metadata in
spotify-web-api-node version 1.4.0 and later
The response object for the same request in earlier versions than to 2.0.0.
Below are examples for all helper functions. Longer examples of some requests can be found in the examples folder.
Please note that since version 1.3.2 all methods accept an optional callback method as their last parameter. These examples however only use promises.
var SpotifyWebApi = require'spotify-web-api-node';var spotifyApi = ;// Get multiple albumsspotifyApigetAlbums'5U4W9E5WsYb2jUQWePT8Xm' '3KyVcddATClQKIdtaap4bV'thenconsole.log'Albums information' databody;console.errorerr;;// Get an artistspotifyApigetArtist'2hazSY4Ef3aB9ATXW7F5w3'thenconsole.log'Artist information' databody;console.errorerr;;// Get multiple artistsspotifyApigetArtists'2hazSY4Ef3aB9ATXW7F5w3' '6J6yx1t3nwIDyPXk5xa7O8'thenconsole.log'Artists information' databody;console.errorerr;;// Get albums by a certain artistspotifyApigetArtistAlbums'43ZHCT0cAZBISjO8DG9PnE'thenconsole.log'Artist albums' databody;console.errorerr;;// Search tracks whose name, album or artist contains 'Love'spotifyApisearchTracks'Love'thenconsole.log'Search by "Love"' databody;console.errorerr;;// Search artists whose name contains 'Love'spotifyApisearchArtists'Love'thenconsole.log'Search artists by "Love"' databody;console.errorerr;;// Search tracks whose artist's name contains 'Love'spotifyApisearchTracks'artist:Love'thenconsole.log'Search tracks by "Love" in the artist name' databody;console.log'Something went wrong!' err;;// Search playlists whose name or description contains 'workout'spotifyApisearchPlaylists'workout'thenconsole.log'Found playlists are' databody;console.log'Something went wrong!' err;;// Get tracks in an albumspotifyApigetAlbumTracks'41MnTivkwTO3UUJ8DrqEJJ' limit : 5 offset : 1thenconsole.logdatabody;console.log'Something went wrong!' err;;// Get an artist's top tracksspotifyApigetArtistTopTracks'0oSGxfWSnnOXhD2fKuz2Gy' 'GB'thenconsole.logdatabody;console.log'Something went wrong!' err;;// Get artists related to an artistspotifyApigetArtistRelatedArtists'0qeei9KQnptjwb8MgkqEoy'thenconsole.logdatabody;doneerr;;/** User methods*/// Get a userspotifyApigetUser'petteralexis'thenconsole.log'Some information about this user' databody;console.log'Something went wrong!' err;;// Get the authenticated userspotifyApigetMethenconsole.log'Some information about the authenticated user' databody;console.log'Something went wrong!' err;;/** Playlist methods*/// Get a playlistspotifyApigetPlaylist'thelinmichael' '5ieJqeLJjjI8iJWaxeBLuK'thenconsole.log'Some information about this playlist' databody;console.log'Something went wrong!' err;;// Get a user's playlistsspotifyApigetUserPlaylists'thelinmichael'thenconsole.log'Retrieved playlists' databody;console.log'Something went wrong!' err;;// Create a private playlistspotifyApicreatePlaylist'thelinmichael' 'My Cool Playlist' 'public' : falsethenconsole.log'Created playlist!';console.log'Something went wrong!' err;;// Add tracks to a playlistspotifyApiaddTracksToPlaylist'thelinmichael' '5ieJqeLJjjI8iJWaxeBLuK' "spotify:track:4iV5W9uYEdYUVa79Axb7Rh" "spotify:track:1301WleyT98MSxVHPZCA6M"thenconsole.log'Added tracks to playlist!';console.log'Something went wrong!' err;;// Add tracks to a specific position in a playlistspotifyApiaddTracksToPlaylist'thelinmichael' '5ieJqeLJjjI8iJWaxeBLuK' "spotify:track:4iV5W9uYEdYUVa79Axb7Rh" "spotify:track:1301WleyT98MSxVHPZCA6M"position : 5thenconsole.log'Added tracks to playlist!';console.log'Something went wrong!' err;;// Remove tracks from a playlist at a specific positionspotifyApiremoveTracksFromPlaylistByPosition'thelinmichael' '5ieJqeLJjjI8iJWaxeBLuK' 0 2 130 "0wD+DKCUxiSR/WY8lF3fiCTb7Z8X4ifTUtqn8rO82O4Mvi5wsX8BsLj7IbIpLVM9"thenconsole.log'Tracks removed from playlist!';console.log'Something went wrong!' err;;// Remove all occurrence of a trackvar tracks = tracks : uri : "spotify:track:4iV5W9uYEdYUVa79Axb7Rh" ;var options = snapshot_id : "0wD+DKCUxiSR/WY8lF3fiCTb7Z8X4ifTUtqn8rO82O4Mvi5wsX8BsLj7IbIpLVM9" ;spotifyApiremoveTracksFromPlaylist'thelinmichael' '5ieJqeLJjjI8iJWaxeBLuK' tracks optionsthenconsole.log'Tracks removed from playlist!';console.log'Something went wrong!' err;;// Reorder the first two tracks in a playlist to the place before the track at the 10th positionvar options = "range_length" : 2 ;spotifyApireorderTracksInPlaylist'thelinmichael' '5ieJqeLJjjI8iJWaxeBLuK' 0 10 optionsthenconsole.log'Tracks reordered in playlist!';console.log'Something went wrong!' err;;// Change playlist detailsspotifyApichangePlaylistDetails'thelinmichael' '5ieJqeLJjjI8iJWaxeBLuK'name: 'This is a new name for my Cool Playlist, and will become private''public' : falsethenconsole.log'Playlist is now private!';console.log'Something went wrong!' err;;// Follow a playlist (privately)spotifyApifollowPlaylist'thelinmichael' '5ieJqeLJjjI8iJWaxeBLuK''public' : falsethenconsole.log'Playlist successfully followed privately!';console.log'Something went wrong!' err;;// Unfollow a playlistspotifyApiunfollowPlaylist'thelinmichael' '5ieJqeLJjjI8iJWaxeBLuK'thenconsole.log'Playlist successfully unfollowed!';console.log'Something went wrong!' err;;// Check if Users are following a PlaylistthendatabodyforEachconsole.log"User is following: " + isFollowing;;console.log'Something went wrong!' err;;;/** Your Music library methods*/// Get tracks in the signed in user's Your Music libraryspotifyApigetMySavedTrackslimit : 2offset: 1thenconsole.log'Done!';console.log'Something went wrong!' err;;// Check if tracks are in the signed in user's Your Music libraryspotifyApicontainsMySavedTracks"5ybJm6GczjQOgTqmJ0BomP"then// An array is returned, where the first element corresponds to the first track ID in the queryvar trackIsInYourMusic = databody0;if trackIsInYourMusicconsole.log'Track was found in the user\'s Your Music library';elseconsole.log'Track was not found.';console.log'Something went wrong!' err;;// Remove tracks from the signed in user's Your Music libraryspotifyApiremoveFromMySavedTracks"3VNWq8rTnQG6fM1eldSpZ0"thenconsole.log'Removed!';console.log'Something went wrong!' err;;;// Add tracks to the signed in user's Your Music libraryapiaddToMySavedTracks"3VNWq8rTnQG6fM1eldSpZ0"thenconsole.log'Added track!';console.log'Something went wrong!' err;;;/** Browse methods*/// Retrieve new releasesspotifyApigetNewReleases limit : 5 offset: 0 country: 'SE'thenconsole.logdatabody;done;console.log"Something went wrong!" err;;;// Retrieve featured playlistsspotifyApigetFeaturedPlaylists limit : 3 offset: 1 country: 'SE' locale: 'sv_SE' timestamp:'2014-10-23T09:00:00'thenconsole.logdatabody;console.log"Something went wrong!" err;;// Get a List of CategoriesspotifyApigetCategorieslimit : 5offset: 0country: 'SE'locale: 'sv_SE'thenconsole.logdatabody;console.log"Something went wrong!" err;;// Get a Category (in Sweden)spotifyApigetCategory'party'country: 'SE'locale: 'sv_SE'thenconsole.logdatabody;console.log"Something went wrong!" err;;// Get Playlists for a Category (Party in Brazil)spotifyApigetPlaylistsForCategory'party'country: 'BR'limit : 2offset : 0thenconsole.logdatabody;console.log"Something went wrong!" err;;
// track detail information for album tracksspotifyApigetAlbum'5U4W9E5WsYb2jUQWePT8Xm'thenreturn databodytracksmap return tid; ;thenreturn spotifyApigetTrackstrackIds;thenconsole.logdatabody;catchconsole.errorerror;;// album detail for the first 10 Elvis' albumsspotifyApigetArtistAlbums'43ZHCT0cAZBISjO8DG9PnE' limit: 10thenreturn databodyalbumsmap return aid; ;thenreturn spotifyApigetAlbumsalbums;thenconsole.logdatabody;;
Supplying an access token in a request is not always required by the API (see the Endpoint reference for details), but it will give your application benefits such as a higher rate limit. This wrapper supports two authorization flows; The Authorization Code flow (signed by a user), and the Client Credentials flow (application authentication - the user isn't involved). See Spotify's Authorization guide for detailed information on these flows.
With the application created and its redirect URI set, the only thing necessary for the application to retrieve an authorization code is the user's permission. Which permissions you're able to ask for is documented in Spotify's Using Scopes section.
In order to get permissions, you need to direct the user to our Accounts service. Generate the URL by using the wrapper's authorization URL method.
var scopes = 'user-read-private' 'user-read-email'redirectUri = ''clientId = '5fe01282e44241328a84e7c5cc169165'state = 'some-state-of-my-choice';// Setting credentials can be done in the wrapper's constructor, or using the API object's setters.var spotifyApi =redirectUri : redirectUriclientId : clientId;// Create the authorization URLvar authorizeURL = spotifyApicreateAuthorizeURLscopes state;//console.logauthorizeURL;
The example below uses a hardcoded authorization code, retrieved from the Accounts service as described above.
var credentials =clientId : 'someClientId'clientSecret : 'someClientSecret'redirectUri : '';var spotifyApi = credentials;// The code that's returned as a query parameter to the redirect URIvar code = 'MQCbtKe23z7YzzS44KzZzZgjQa621hgSzHN';// Retrieve an access token and a refresh tokenspotifyApiauthorizationCodeGrantcodethenconsole.log'The token expires in ' + databody'expires_in';console.log'The access token is ' + databody'access_token';console.log'The refresh token is ' + databody'refresh_token';// Set the access token on the API object to use it in later callsspotifyApisetAccessTokendatabody'access_token';spotifyApisetRefreshTokendatabody'refresh_token';console.log'Something went wrong!' err;;
Since the access token was set on the api object in the previous success callback, it's going to be used in future calls. As it was retrieved using the Authorization Code flow, it can also be refreshed unless it has expired.
// clientId, clientSecret and refreshToken has been set on the api object previous to this call.spotifyApirefreshAccessTokenthenconsole.log'The access token has been refreshed!';console.log'Could not refresh access token' err;;
The Client Credential flow doesn't require the user to give permissions, so it's suitable for requests where the application just needs to authenticate itself. This is the case with for example retrieving a playlist. However, note that the access token cannot be refreshed, and that it isn't connected to a specific user.
var clientId = 'someClientId'clientSecret = 'someClientSecret';// Create the api object with the credentialsvar spotifyApi =clientId : clientIdclientSecret : clientSecret;// Retrieve an access token.spotifyApiclientCredentialsGrantthenconsole.log'The access token expires in ' + databody'expires_in';console.log'The access token is ' + databody'access_token';// Save the access token so that it's used in future callsspotifyApisetAccessTokendatabody'access_token';console.log'Something went wrong when retrieving an access token' err;;
Credentials are either set when constructing the API object or set after the object has been created using setters. They can be set all at once or one at a time.
Using setters, getters and resetters.
// Use setters to set all credentials one by onevar spotifyApi = ;spotifyApisetAccessToken'myAccessToken';spotifyApisetRefreshToken'myRefreshToken';spotifyApisetRedirectURI'';spotifyApisetClientId'myOwnClientId';spotifyApisetClientSecret'someSuperSecretString';// Set all credentials at the same timespotifyApisetCredentials'accessToken' : 'myAccessToken''refreshToken' : 'myRefreshToken''redirectUri' : '''clientId ' : 'myClientId''clientSecret' : 'myClientSecret';// Get the credentials one by oneconsole.log'The access token is ' + spotifyApigetAccessToken;console.log'The refresh token is ' + spotifyApigetRefreshToken;console.log'The redirectURI is ' + spotifyApigetRedirectURI;console.log'The client ID is ' + spotifyApigetClientId;console.log'The client secret is ' + spotifyApigetClientSecret;// Get all credentialsconsole.log'The credentials are ' + spotifyApigetCredentials;// Reset the credentialsspotifyApiresetAccessToken;spotifyApiresetRefreshToken;spotifyApiresetRedirectURI;spotifyApiresetClientId;spotifyApiresetClientSecret;spotifyApiresetCode;// Reset all credentials at the same timespotifyApiresetCredentials;
Using the constructor.
// Set necessary parts of the credentials on the constructorvar spotifyApi =clientId : 'myClientId'clientSecret : 'myClientSecret';// Get an access token and 'save' it using a setterspotifyApiclientCredentialsGrantthenconsole.log'The access token is ' + databody'access_token';spotifyApisetAccessTokendatabody'access_token';console.log'Something went wrong!' err;;
// Set the credentials when making the requestvar spotifyApi =accessToken : 'njd9wng4d0ycwnn3g4d1jm30yig4d27iom5lg4d3';// Do search using the access tokenspotifyApisearchTracks'artist:Love'thenconsole.logdatabody;console.log'Something went wrong!' err;;
// Set the credentials when making the requestvar spotifyApi =accessToken : 'njd9wng4d0ycwnn3g4d1jm30yig4d27iom5lg4d3';// Get tracks in a playlistapigetPlaylistTracks'thelinmichael' '3ktAYNcRHpazJ9qecm3ptn' 'offset' : 1 'limit' : 5 'fields' : 'items'thenconsole.log'The playlist contains these tracks' databody;console.log'Something went wrong!' err;;
- Breaking change: Response object changed. Add headers and status code to all responses to enable users to implement caching.
- Add language binding for Reorder tracks in a Playlist
- Add language binding for Remove tracks in a Playlist by Position
- Add Search for Playlists endpoint.
- Add market parameter to endpoints supporting Track Relinking.
- Improve SEO by adding keywords to the package.json file. ;-)
- Add Check if Users are Following Playlist endpoint.
- Add missing options parameter in createPlaylist (issue #19). Thanks for raising this allinallin.
- Add ability to use callback methods instead of promise.
- Bugfix. api.addTracksToPlaylist tracks parameter can be a string or an array. Thanks ofagbemi!
- Specify module's git repository. Thanks vincentorback.
- Allow options to be set when retrieving a user's playlists. Thanks EaterOfCode.
- Add Replace tracks in a Playlist endpoint
- Add Remove tracks in a Playlist endpoint
- Return errors as Error objects instead of unparsed JSON. Thanks niftylettuce.
- Add Your Music Endpoints (Add tracks, Remove tracks, Contains tracks, Get tracks).
- Documentation updates (change scope name of playlist-modify to playlist-modify-public, and a fix to a parameter type). Thanks JMPerez and matiassingers.
- Add Related artists endpoint