36  The Spotify API

In this notebook we will fetch and process music data from Spotify, using the Spotify API.

Spotify for Developers logo.

Specifically we will lookup and display the top tracks for any given artist.

36.1 Setup

Sometimes when working with an API we will fetch data directly, using a web request. However in other cases there might be a Python package that can help make our lives easier, especially when there are complicated authorization steps involved.

For this demo, we will use the spotipy package, which provides a high level interface into the Spotify API.

Installing the spotipy package into the notebook environment:

%%capture
!pip install spotipy

Ensuring the package has been installed:

!pip list | grep spotipy
spotipy                               2.25.1

To interface with the Spotify API, you need to create a Spotify API Client application, with corresponding credentials (i.e. the “client identifier” and “client secret”).

Before proceeding, set these credentials as notebook secrets called SPOTIPY_CLIENT_ID and SPOTIPY_CLIENT_SECRET, respectively.

Accessing the credentials from notebook secrets:

from google.colab import userdata

SPOTIPY_CLIENT_ID = userdata.get("SPOTIPY_CLIENT_ID")
SPOTIPY_CLIENT_SECRET = userdata.get("SPOTIPY_CLIENT_SECRET")

Initializing a new Spotify API client, using the provided credentials:


from spotipy import Spotify
from spotipy.oauth2 import SpotifyClientCredentials

creds = SpotifyClientCredentials(
    client_id=SPOTIPY_CLIENT_ID,
    client_secret=SPOTIPY_CLIENT_SECRET
)

client = Spotify(client_credentials_manager=creds)
print("CLIENT:", type(client))
CLIENT: <class 'spotipy.client.Spotify'>

The client object will allow us to make various requests to the API.

36.2 Example: Artist Top Tracks

To get the top tracks for a given artist, we will use the client object’s artist_top_tracks method, which issues a request to the Spotify API’s Artist Top Tracks endpoint.

Since this request requires us to supply the official Spotify identifier of a given artist, we’ll need to first get the artist idenfier, and then get their top tracks.

Selecting an artist name:

artist_name = input("Please choose an artist: ")
artist_name
Please choose an artist: Dua Lipa
'Dua Lipa'

Getting the official Spotify identifier for the given artist (assuming the first artist is the closest match):

artist_response = client.search(q=artist_name, type='artist', limit=1)
artist_response
{'artists': {'href': 'https://api.spotify.com/v1/search?offset=0&limit=1&query=Dua%20Lipa&type=artist',
  'limit': 1,
  'next': 'https://api.spotify.com/v1/search?offset=1&limit=1&query=Dua%20Lipa&type=artist',
  'offset': 0,
  'previous': None,
  'total': 804,
  'items': [{'external_urls': {'spotify': 'https://open.spotify.com/artist/6M2wZ9GZgrQXHCFfjv46we'},
    'followers': {'href': None, 'total': 46530425},
    'genres': ['pop'],
    'href': 'https://api.spotify.com/v1/artists/6M2wZ9GZgrQXHCFfjv46we',
    'id': '6M2wZ9GZgrQXHCFfjv46we',
    'images': [{'url': 'https://i.scdn.co/image/ab6761610000e5eb0c68f6c95232e716f0abee8d',
      'height': 640,
      'width': 640},
     {'url': 'https://i.scdn.co/image/ab676161000051740c68f6c95232e716f0abee8d',
      'height': 320,
      'width': 320},
     {'url': 'https://i.scdn.co/image/ab6761610000f1780c68f6c95232e716f0abee8d',
      'height': 160,
      'width': 160}],
    'name': 'Dua Lipa',
    'popularity': 89,
    'type': 'artist',
    'uri': 'spotify:artist:6M2wZ9GZgrQXHCFfjv46we'}]}}

Parsing the response data:

artist = artist_response["artists"]["items"][0]
artist
{'external_urls': {'spotify': 'https://open.spotify.com/artist/6M2wZ9GZgrQXHCFfjv46we'},
 'followers': {'href': None, 'total': 46530425},
 'genres': ['pop'],
 'href': 'https://api.spotify.com/v1/artists/6M2wZ9GZgrQXHCFfjv46we',
 'id': '6M2wZ9GZgrQXHCFfjv46we',
 'images': [{'url': 'https://i.scdn.co/image/ab6761610000e5eb0c68f6c95232e716f0abee8d',
   'height': 640,
   'width': 640},
  {'url': 'https://i.scdn.co/image/ab676161000051740c68f6c95232e716f0abee8d',
   'height': 320,
   'width': 320},
  {'url': 'https://i.scdn.co/image/ab6761610000f1780c68f6c95232e716f0abee8d',
   'height': 160,
   'width': 160}],
 'name': 'Dua Lipa',
 'popularity': 89,
 'type': 'artist',
 'uri': 'spotify:artist:6M2wZ9GZgrQXHCFfjv46we'}

Displaying information about the artist, including their unique identifier:

from IPython.display import Image, display

followers = artist['followers']['total']
image_url = artist["images"][0]["url"]

print("ARTIST:", artist["name"])
print("ID:", artist["id"])
print("POPULARITY:", artist["popularity"])
print(f"FOLLOWERS: {followers:,}")
print("GENRES:", artist["genres"])

display(Image(url=image_url, height=200))
ARTIST: Dua Lipa
ID: 6M2wZ9GZgrQXHCFfjv46we
POPULARITY: 89
FOLLOWERS: 46,530,425
GENRES: ['pop']

Fetching the artist’s top tracks (given their official Spotify artist identifier):

artist_id = artist["id"]
tracks_response = client.artist_top_tracks(artist_id)
print(type(tracks_response))
tracks_response.keys()
<class 'dict'>
dict_keys(['tracks'])

Exploring and processing the response data:

top_tracks = tracks_response["tracks"]
print(type(top_tracks))
len(top_tracks)
<class 'list'>
10

It looks like the API returned information about ten tracks. Investigating the structure of one of the tracks:

track = top_tracks[0]
type(track)
dict
track.keys()
dict_keys(['album', 'artists', 'available_markets', 'disc_number', 'duration_ms', 'explicit', 'external_ids', 'external_urls', 'href', 'id', 'is_local', 'is_playable', 'name', 'popularity', 'preview_url', 'track_number', 'type', 'uri'])
from datetime import timedelta
from IPython.display import Image, display

artist_names = [artist["name"] for artist in track["artists"]]

duration_s = int(track['duration_ms'] / 1000)
track_duration = timedelta(seconds=duration_s)

print(f"TRACK: '{track['name']}'")
print("ARTIST NAME(S):", artist_names)
print(f"ALBUM: '{track['album']['name']}'")
print("RELEASE DATE:", track["album"]["release_date"])
print("DURATION:", str(track_duration))
print("MARKETS:", len(track["available_markets"]))
print("POPULARITY SCORE:", track["popularity"])

album_img_url = track["album"]["images"][0]["url"]
display(Image(url=album_img_url, width=200))
TRACK: 'New Rules'
ARTIST NAME(S): ['Dua Lipa']
ALBUM: 'Dua Lipa (Deluxe)'
RELEASE DATE: 2017-06-02
DURATION: 0:03:29
MARKETS: 179
POPULARITY SCORE: 81

Sorting the top tracks in order of their popularity:

from operator import itemgetter

top_tracks = sorted(top_tracks, key=itemgetter("popularity"), reverse=True)

Looping through the top tracks to display the name and popularity score of each:

for i, track in enumerate(top_tracks):
    print(i+1, track["name"], "|", track["popularity"])
1 Don't Start Now | 82
2 Levitating (feat. DaBaby) | 81
3 New Rules | 81
4 Houdini | 81
5 Dance The Night - From Barbie The Album | 80
6 Levitating | 80
7 IDGAF | 78
8 Training Season | 77
9 One Kiss (with Dua Lipa) | 76
10 Cold Heart - PNAU Remix | 69

Alright, we did it!

Getting an artist’s top tracks is just one capability of the Spotify API.

After reading through more of the spotipy package documentation, what other capabilities are you interested in exploring?