Getting your latest releases from Deezer with Python

Have you ever felt like you’ve missed an album from your favorite artist? If yes then this article is just for you.

Here we will fetch your followed artists and their albums from Deezer API to see whether you missed any releases or not. We will use Python to do all the work.

Getting started

First, you’ll need to know your ID. You can get it by opening Deezer in a browser and visiting your profile.

Now, if you check the URL address you should see something like this

https://www.deezer.com/en/profile/700513741

A number at the end of the URL is your ID (mine is 700513741). Let’s store it in a variable.

deezer_id = 700513741

If you want to get IDs of users of your project you’ll need to create a Deezer application and connect that application to your project. For more information on how to do that you can check out this guide.

Fetching information about you

Archive storage

To begin our fetching journey let’s fetch ourselves first. To fetch a user we can use Deezer’s User endpoint. We just need to send a request to a URL specified in the documentation and information about a user should be in the response.

But before doing any requests with Python we can try doing some requests in Deezer’s API explorer.

The docs say that the URL for getting info about a user is https://api.deezer.com/user/me. but if we try to perform a request to the endpoint we receive an error

An active access token must be used to query information about the current user

This means that we have to get a token that is related to our user for Deezer to know who is “me”. But we all like doing things in an easy way and getting that access token is just too hard. This is exactly why I asked you to get your ID by yourself. Now we can just replace /me with your ID and everything should be working. Here’s what I got in the API explorer

Successfull response with a user in the API explorer

Making real requests

Making requests in Python is very easy with requests library. If you don’t have the library installed you can use an official installation guide. Once you have requests installed we can proceed to coding.

To send a regular GET request with requests the library provides us a get method which just needs a URL

import requests
url = f"https://api.deezer.com/user/{deezer_id}"
user_response = requests.get(url)

The user_response variable should now contain lots of data that happened during the request. What interests us is what the body of the response. We can get it with response.content method

user_response.content
# => b'{"id":700513741, "name":"hmlON", ...}'

As we can the response contains a JSON string. We could parse it with a json library but requests have worked everything out for is — we can just use a json() method

user_response.json()
# => {'id': 700513741, 'name': 'hmlON', ...}

Now we have a normal dictionary with which we can work. Let’s finish our “hello world” program (Deezer API edition) before we continue making other requests

name = user_response.json()['name']
print(f"Hello, {name}!")

Fetching your favorite artists

Your favorite artist's concert

Your favorite artists can be found on a User / Artists endpoint. As usual, it suggests to use /me in the URL but we’re smarter then that and will use the ID. So let’s test the endpoint.

artists_url = f"https://api.deezer.com/user/{deezer_id}/artists"
artists_response = requests.get(artists_url)
artists_response.json()
# => {
#  "data": [
#    {
#      "id": "296861",
#      "name": "The Neighbourhood",
#	   ...
#    },
#    ...
#  ]
#  ...
#  "total": 30,
#  "next": "https://api.deezer.com/user/700513741/artists?index=25"
# }

The endpoint seems to be working. As we can see from the response, we have a couple of interesting fields here:

The next parameter is empty if a response returned the last page of data. This means that if we want to just take a glance at artists we can send requests as is. But if we want to fetch all data (like we do now) we would have to use this parameter.

The algorithm for fetching all records is pretty simple — we go to the next page while it is present. Let’s go ahead and implement it

artists = [] 			   # we'll store artists here as we go through the pages
all_artists_loaded = False # in the beginning nothing is loaded
url = f"https://api.deezer.com/user/{deezer_id}/artists"

while not all_artists_loaded:
    response = requests.get(url).json()
    artists += response['data']   # data attribute contains artists from the request
    if response.get('next'):      # there are more artists on the next page
        url = response['next']    # we will continue to fetch from the next page
    else:                         # there are no more followed artists
        all_artists_loaded = True # we will end the loop

The algorithm is pretty straightforward but there is one thing I would like to note. When I’m checking whether there is a next page I use response.get('next') instead of response['next']. The difference here is that when the next key is not present in the response the response.get('next') method will return nothing while the regular response['next'] will raise an error.

response = {'data': ['...']} # response without the 'next' attribute

response['next']
# raises KeyError: 'next'

response.get('next')
# => None

Fetching your favorite artists’ releases

Vinil albums store

Now that we have all followed artists we can fetch their albums. The Artist / Albums endpoint is quite suitable for this task.

This time we would need to loop over each artist and save all albums in an array. To fetch all releases for each artist we would use the same algorithm as we’ve used to fetch artists.

releases = [] # we'll store all releases here

for artist in artists:
    # the old algorithm is still working here
    all_releases_loaded = False
    artist_id = artist['id']
    url = f"https://api.deezer.com/artist/{artist_id}/albums"

    while not all_releases_loaded:
        response = requests.get(url).json()
        releases += response['data']
        if response.get('next'):
            url = response['next']
        else:
            all_releases_loaded = True

Pretty much the same as before. But there is one problem which we will notice if we look at any release

releases[-1]
# {
#  'cover': 'https://api.deezer.com/album/40571541/image',
#  'explicit_lyrics': True,
#  'fans': 52,
#  'genre_id': 116,
#  'id': 40571541,
#  'link': 'https://www.deezer.com/album/40571541',
#  'record_type': 'single',
#  'release_date': '2017-04-18',
#  'title': 'DEADMAN WUNDERLAND',
#  'tracklist': 'https://api.deezer.com/album/40571541/tracks',
#  'type': 'album'
# }

The problem is that we don’t know who the artist is. We can solve it in two ways:

  1. by storing artists in a dictionary with their ID as a key and adding artist_id to all releases
  2. by storing full title (with artist’s name) in the release

I will go with the second one since it would be easier to do but if you would like to implement the first solution or any other please share it in the comments.

To save the full title in a release we would need to store artist’s songs in a temporary array. And when all albums are fetched we would need to add the full title to them.

releases = [] # we'll store all releases here

for artist in artists:
    # this time we'll store releases in a temporary array
    current_artist_releases = []

    # nothing changed here
    all_releases_loaded = False
    artist_id = artist['id']
    url = f"https://api.deezer.com/artist/{artist_id}/albums"

    while not all_releases_loaded:
        response = requests.get(url).json()

        # now we're saving each page's response to current_artists_releases
        # instead of straight to releases
        current_artist_releases += response['data']
        
        # this stays the same too
        if response.get('next'):
            url = response['next']
        else:
            all_releases_loaded = True
            
    # and after we've fetched all releases
    # we can add full title to all of them
    for release in current_artist_releases:
        full_title = f"{artist['name']} — {release['title']}"
        release['full_title'] = full_title
        
    # and only after we every release from current artist
    # has a full title we can add them to the main releases
    releases += current_artist_releases

So now all releases should have a full title

releases[-1]['full_title']
# => 'Aries — DEADMAN WUNDERLAND'

So what have you missed?

Let’s check what was released during the last year. If you haven’t checked it, you might be surprised by some interesting albums.

To begin, we need to filter releases so that only that were created during the last year are left. To do this we will use a standard datetime library to get a date of the last year

import datetime

today = datetime.date.today()
print(today)
# => 2018-12-13

year_ago = today - datetime.timedelta(days=365)
print(year_ago)
# => 2017-12-13

Then, to filter we need to compare the release date with our year_ago variable. The only problem here is that release date is a string

releases[-1]['release_date']
# => '2017-04-18'

And we can’t compare string with a date in Python. So a way out of this is to convert a string into a date. The datetime library has a function just for our case called datetime.strptime. It needs a string (the release date) and it’s format.

As we can see, release_date format is 'year-month-day'. With a little help of documentation, this converts into '%Y-%m-%d'

datetime.datetime.strptime(releases[-1]['release_date'], '%Y-%m-%d').date()
# => datetime.date(2017, 4, 18)

Let’s store the release_date as a date instead of a string for all releases.

for release in releases:
    previous_date = release['release_date']
    new_date = datetime.datetime.strptime(previous_date, '%Y-%m-%d').date()
    release['release_date'] = new_date

Now we can finally filter our releases to get only the ones from last year

latest_releases = [
    release for release in releases
	if release['release_date'] > year_ago
]

After that, all of the last year’s releases are stored in the latest_releases variable. Now we need to sort those releases by date to have them listed chronologically

latest_releases = sorted(latest_releases, key=lambda release: release['release_date'])

And finally, we can print those releases

for release in latest_releases:
    date = release['release_date']
    title = release['full_title']
    print(f"{date}: {title}")
# ...
# 2018-10-25: Aries — BLOSSOM
# 2018-11-02: Panic! At the Disco — The Greatest Show
# 2018-11-02: The Neighbourhood — Hard To Imagine The Neighbourhood Ever Changing
# 2018-11-09: Muse — Simulation Theory (Super Deluxe)
# 2018-11-09: Imagine Dragons — Origins
# 2018-11-09: Imagine Dragons — Origins (Deluxe)
# 2018-11-09: Goody Grace — Nostalgia Is A Lie
# 2018-11-30: Arctic Monkeys — Tranquility Base Hotel & Casino

If you’ve followed along this far please share your latest releases for the last month in the comments.

Conclusion

In this article I’ve covered:

Congratulations, now you know how to check for new releases from artists that you follow. If you’re like me and hate missing out on new releases from your favorite artists, I’ve built a website just for this purpose.

If you would like to run the code by yourself and don’t want to scramble it from the article pieces by pieces, I’ve uploaded it into a gist on GitHub.

Also, this is the third part of a series of articles about the MuN. Stay tuned for part 4. You can find the code of this project, as well as my other projects, on my GitHub page. Leave your comments down below and follow me if you liked this article.