October 7, 2019

Tutorial: Getting Music Data with the Last.fm API using Python

APIs allow us to make requests from servers to retrieve data. APIs are useful for many things, but one is to be able to create a unique dataset for a data science project. In this tutorial, we're going to learn some advanced techniques for working with the Last.fm API.

In our beginner Python API tutorial, we worked with a simple API that was ideal for teaching the basics:

  • It had a few, easy to understand end points.
  • Because it didn't require authentication, we didn't have to worry about how to tell the API that we had perlesson to use it.
  • The data that each end point responded with was small and had an easy-to-understand structure.

In reality, most APIs are more complex than this, and so to work with them you need to understand some more advanced concepts. Specifically, we're going to learn:

  • How to authenticate yourself with an API key.
  • How to use rate limiting and other techniques to work within the guidelines of an API.
  • How to use pagination to work with large responses.

This tutorial assumes you understand the basics of working with an API in Python. If you don't, we recommend our beginner API tutorial to start. We also assume you have an intermediate knowledge of Python and pandas. If you don't, you can start learning for free with our Python Fundamentals course.

Working with the Last.fm API

We'll be working with the Last.fm API. Last.fm is a music service that builds personal profiles by connecting to music streaming apps like iTunes, Spotify and others like it and keeping track of the music you listen to.

They provide free access to their API so that music services can send them data, but also provide endpoints that summarize all the data that Last.fm has on various artists, songs, and genres. We'll be building a dataset of popular artists using their API.

Following API Guidelines

When working with APIs, it's important to follow their guidelines. If you don't, you can get yourself banned from using the API. Beyond that, especially when a company provides an API for free, it's good to respect their limitations and guidelines since they're providing something for nothing.

Looking at the Introduction Page in the API documentation, we can notice a few important guidelines:

Please use an identifiable User-Agent header on all requests. This helps our logging and reduces the risk of you getting banned.

When you make a request to the last.fm API, you can identify yourself using headers. Last.fm wants us to specify a user-agent in the header so they know who we are. We'll learn how to do that when we make our first request in a moment.

Use common sense when deciding how many calls to make. For example, if you're making a web application, try not to hit the API on page load. Your account may be suspended if your application is continuously making several calls per second.

In order to build our data set, we're going to need to make thousands of requests to the Last.fm API. While they don't provide a specific limit in their documentation, they do advise that we shouldn't be continuously making many calls per second. In this tutorial we're going to learn a few strategies for rate limiting, or making sure we don't hit their API too much, so we can avoid getting banned.

Before we make our first request, we need learn how to authenticate with the Last.fm API

Authenticating with API Keys

The majority of APIs require you to authenticate yourself so they know you have perlesson to use them. One of the most common forms of authentication is to use an API Key, which is like a password for using their API. If you don't provide an API key when making a request, you will get an error.

The process for using an API key works like this:

  1. You create an account with the provider of the API.
  2. You request an API key, which is usually a long string like 54686973206973206d7920415049204b6579.
  3. You record your API key somewhere safe, like a password keeper. If someone gets your API key, they can use the API pretending to be you.
  4. Every time you make a request, you provide the API key to authenticate yourself.

To get an API key for Last.fm, start by creating an account. After you create your account, you should be taken to this form:

Create an API account

Fill out each field with information about how you plan to use the API. You can leave the 'Callback URL' field blank, as this is only used if you are building a web application to authenticate as a specific Last.fm user.

After you submit the form, you will get details of your API key and shared secret:

Last.fm API keys

Note these down somewhere safe - we won't need to use the shared secret for this tutorial, but it's good to have it noted down in case you want to do something that requires you to authenticate as a specific user.

Making our first API request

In order to create a dataset of popular artists, we'll be working with the chart.getTopArtists endpoint.

Looking at the Last.fm API documentation, we can observe a few things:

  • It looks like there is only one real endpoint, and each "endpoint" is actually specified by using the method parameter.
  • The documentation says This service does not require authentication. While this might seem slightly confusing at first, what it's telling us is that we don't need to authenticate as a specific Last.fm user. If you look above this, you can see that we do need to provide our API key.
  • The API can return results in multiple formats - we'll specify JSON so we can leverage what we already know about working with APIs in Python

Before we start, remember that we need to provide a user-agent header to identify ourselves when we make a request. With the Python requests library, we specify headers using the headers parameter with a dictionary of headers like so:

headers = {
    'user-agent': 'Dataquest'
}

r = requests.get('https://my-api-url', headers=headers)

We'll start by defining our API key and a user-agent (the API key shown in this tutorial is not a real API key!)

API_KEY = '54686973206973206d7920415049204b6579'
USER_AGENT = 'Dataquest'

Next, we'll import the requests library, create a dictionary for our headers and parameters, and make our first request!

import requests

headers = {
    'user-agent': USER_AGENT
}

payload = {
    'api_key': API_KEY,
    'method': 'chart.gettopartists',
    'format': 'json'
}

r = requests.get('https://ws.audioscrobbler.com/2.0/', headers=headers, params=payload)
r.status_code
200

Our request returned a status code of '200', so we know it was successful.

Before we look at the data returned by our request, let's think about the fact that we're going to make many requests during this tutorial. In those requests, a lot of the functionality is going to be the same:

  • We'll use the same URL
  • We'll use the same API key
  • We'll specify JSON as our format.
  • We'll use the same headers.

To save ourselves time, we're going to create a function that does a lot of this work for us. We'll provide the function with a payload dictionary, and then we'll add extra keys to that dictionary and pass it with our other options to make the request.

Let's look at what that function looks like:

def lastfm_get(payload):
    # define headers and URL
    headers = {'user-agent': USER_AGENT}
    url = 'https://ws.audioscrobbler.com/2.0/'

    # Add API key and format to the payload
    payload['api_key'] = API_KEY
    payload['format'] = 'json'

    response = requests.get(url, headers=headers, params=payload)
    return response

And let's see how much it simplifies making our earlier request:

r = lastfm_get({
    'method': 'chart.gettopartists'
})

r.status_code
200

As we learned in our beginner Python API tutorial, most APIs return data in a JSON format, and we can use the Python json module to print the JSON data in an easiler to understand format.

Let's re-use the jprint() function we created in that tutorial and print our response from the API:

import json

def jprint(obj):
    # create a formatted string of the Python JSON object
    text = json.dumps(obj, sort_keys=True, indent=4)
    print(text)

jprint(r.json())
{
    "artists": {
        "@attr": {
            "page": "1",
            "perPage": "50",
            "total": "2901036",
            "totalPages": "58021"
        },
        "artist": [
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1957174",
                "mbid": "b7539c32-53e7-4908-bda3-81449c367da6",
                "name": "Lana Del Rey",
                "playcount": "232808939",
                "streamable": "0",
                "url": "https://www.last.fm/music/Lana+Del+Rey"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "588883",
                "mbid": "",
                "name": "Billie Eilish",
                "playcount": "35520548",
                "streamable": "0",
                "url": "https://www.last.fm/music/Billie+Eilish"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "655052",
                "mbid": "",
                "name": "Post Malone",
                "playcount": "34942708",
                "streamable": "0",
                "url": "https://www.last.fm/music/Post+Malone"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "2290993",
                "mbid": "20244d07-534f-4eff-b4d4-930878889970",
                "name": "Taylor Swift",
                "playcount": "196907702",
                "streamable": "0",
                "url": "https://www.last.fm/music/Taylor+Swift"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1166180",
                "mbid": "f4fdbb4c-e4b7-47a0-b83b-d91bbfcfa387",
                "name": "Ariana Grande",
                "playcount": "124251766",
                "streamable": "0",
                "url": "https://www.last.fm/music/Ariana+Grande"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1716587",
                "mbid": "b8a7c51f-362c-4dcb-a259-bc6e0095f0a6",
                "name": "Ed Sheeran",
                "playcount": "92646726",
                "streamable": "0",
                "url": "https://www.last.fm/music/Ed+Sheeran"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "4084524",
                "mbid": "420ca290-76c5-41af-999e-564d7c71f1a7",
                "name": "Queen",
                "playcount": "197850122",
                "streamable": "0",
                "url": "https://www.last.fm/music/Queen"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "4449534",
                "mbid": "164f0d73-1234-4e2c-8743-d77bf2191051",
                "name": "Kanye West",
                "playcount": "250533444",
                "streamable": "0",
                "url": "https://www.last.fm/music/Kanye+West"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3732023",
                "mbid": "b10bbbfc-cf9e-42e0-be17-e2c3e1d2600d",
                "name": "The Beatles",
                "playcount": "526866107",
                "streamable": "0",
                "url": "https://www.last.fm/music/The+Beatles"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3441963",
                "mbid": "b49b81cc-d5b7-4bdd-aadb-385df8de69a6",
                "name": "Drake",
                "playcount": "147881092",
                "streamable": "0",
                "url": "https://www.last.fm/music/Drake"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "4778856",
                "mbid": "a74b1b7f-71a5-4011-9441-d0b5e4122711",
                "name": "Radiohead",
                "playcount": "507682999",
                "streamable": "0",
                "url": "https://www.last.fm/music/Radiohead"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1528378",
                "mbid": "381086ea-f511-4aba-bdf9-71c753dc5077",
                "name": "Kendrick Lamar",
                "playcount": "109541321",
                "streamable": "0",
                "url": "https://www.last.fm/music/Kendrick+Lamar"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "4618838",
                "mbid": "db36a76f-4cdf-43ac-8cd0-5e48092d2bae",
                "name": "Rihanna",
                "playcount": "204114198",
                "streamable": "0",
                "url": "https://www.last.fm/music/Rihanna"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3550620",
                "mbid": "ada7a83c-e3e1-40f1-93f9-3e73dbc9298a",
                "name": "Arctic Monkeys",
                "playcount": "339370140",
                "streamable": "0",
                "url": "https://www.last.fm/music/Arctic+Monkeys"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3401872",
                "mbid": "5441c29d-3602-4898-b1a1-b77fa23b8e50",
                "name": "David Bowie",
                "playcount": "197606611",
                "streamable": "0",
                "url": "https://www.last.fm/music/David+Bowie"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "680102",
                "mbid": "b7d92248-97e3-4450-8057-6fe06738f735",
                "name": "Shawn Mendes",
                "playcount": "28807659",
                "streamable": "0",
                "url": "https://www.last.fm/music/Shawn+Mendes"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "2093863",
                "mbid": "7e9bd05a-117f-4cce-87bc-e011527a8b18",
                "name": "Miley Cyrus",
                "playcount": "70227591",
                "streamable": "0",
                "url": "https://www.last.fm/music/Miley+Cyrus"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3631084",
                "mbid": "859d0860-d480-4efd-970c-c05d5f1776b8",
                "name": "Beyonc\u00e9",
                "playcount": "165422358",
                "streamable": "0",
                "url": "https://www.last.fm/music/Beyon
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "314392",
                "mbid": "",
                "name": "Lil Nas X",
                "playcount": "6086745",
                "streamable": "0",
                "url": "https://www.last.fm/music/Lil+Nas+X"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3800669",
                "mbid": "122d63fc-8671-43e4-9752-34e846d62a9c",
                "name": "Katy Perry",
                "playcount": "151925781",
                "streamable": "0",
                "url": "https://www.last.fm/music/Katy+Perry"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1184440",
                "mbid": "63aa26c3-d59b-4da4-84ac-716b54f1ef4d",
                "name": "Tame Impala",
                "playcount": "78074910",
                "streamable": "0",
                "url": "https://www.last.fm/music/Tame+Impala"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3877144",
                "mbid": "650e7db6-b795-4eb5-a702-5ea2fc46c848",
                "name": "Lady Gaga",
                "playcount": "292105109",
                "streamable": "0",
                "url": "https://www.last.fm/music/Lady+Gaga"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "840762",
                "mbid": "f6beac20-5dfe-4d1f-ae02-0b0a740aafd6",
                "name": "Tyler, the Creator",
                "playcount": "56318705",
                "streamable": "0",
                "url": "https://www.last.fm/music/Tyler,+the+Creator"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "5429555",
                "mbid": "cc197bad-dc9c-440d-a5b5-d52ba2e14234",
                "name": "Coldplay",
                "playcount": "364107739",
                "streamable": "0",
                "url": "https://www.last.fm/music/Coldplay"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "4665823",
                "mbid": "8bfac288-ccc5-448d-9573-c33ea2aa5c30",
                "name": "Red Hot Chili Peppers",
                "playcount": "298043491",
                "streamable": "0",
                "url": "https://www.last.fm/music/Red+Hot+Chili+Peppers"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "269116",
                "mbid": "50d06c43-5392-4393-ba2d-f091d8167227",
                "name": "Lizzo",
                "playcount": "6953283",
                "streamable": "0",
                "url": "https://www.last.fm/music/Lizzo"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "823024",
                "mbid": "260b6184-8828-48eb-945c-bc4cb6fc34ca",
                "name": "Charli XCX",
                "playcount": "34914186",
                "streamable": "0",
                "url": "https://www.last.fm/music/Charli+XCX"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "2246723",
                "mbid": "8dd98bdc-80ec-4e93-8509-2f46bafc09a7",
                "name": "Calvin Harris",
                "playcount": "75778154",
                "streamable": "0",
                "url": "https://www.last.fm/music/Calvin+Harris"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "4320593",
                "mbid": "9282c8b4-ca0b-4c6b-b7e3-4f7762dfc4d6",
                "name": "Nirvana",
                "playcount": "226060468",
                "streamable": "0",
                "url": "https://www.last.fm/music/Nirvana"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1646166",
                "mbid": "bbfa1e12-8b61-4ed8-bc6e-52d2298f41a2",
                "name": "Tool",
                "playcount": "122824468",
                "streamable": "0",
                "url": "https://www.last.fm/music/Tool"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1008791",
                "mbid": "5a85c140-dcf9-4dd2-b2c8-aff0471549f3",
                "name": "Sam Smith",
                "playcount": "30910342",
                "streamable": "0",
                "url": "https://www.last.fm/music/Sam+Smith"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "2204118",
                "mbid": "bd13909f-1c29-4c27-a874-d4aaf27c5b1a",
                "name": "Fleetwood Mac",
                "playcount": "70574855",
                "streamable": "0",
                "url": "https://www.last.fm/music/Fleetwood+Mac"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3125893",
                "mbid": "83d91898-7763-47d7-b03b-b92132375c47",
                "name": "Pink Floyd",
                "playcount": "318740438",
                "streamable": "0",
                "url": "https://www.last.fm/music/Pink+Floyd"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "273449",
                "mbid": "",
                "name": "BROCKHAMPTON",
                "playcount": "36180740",
                "streamable": "0",
                "url": "https://www.last.fm/music/BROCKHAMPTON"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1326470",
                "mbid": "c8b03190-306c-4120-bb0b-6f2ebfc06ea9",
                "name": "The Weeknd",
                "playcount": "81295303",
                "streamable": "0",
                "url": "https://www.last.fm/music/The+Weeknd"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "4569194",
                "mbid": "b95ce3ff-3d05-4e87-9e01-c97b66af13d4",
                "name": "Eminem",
                "playcount": "204081058",
                "streamable": "0",
                "url": "https://www.last.fm/music/Eminem"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3842009",
                "mbid": "b071f9fa-14b0-4217-8e97-eb41da73f598",
                "name": "The Rolling Stones",
                "playcount": "157067654",
                "streamable": "0",
                "url": "https://www.last.fm/music/The+Rolling+Stones"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1257764",
                "mbid": "e520459c-dff4-491d-a6e4-c97be35e0044",
                "name": "Frank Ocean",
                "playcount": "87152244",
                "streamable": "0",
                "url": "https://www.last.fm/music/Frank+Ocean"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3622199",
                "mbid": "e21857d5-3256-4547-afb3-4b6ded592596",
                "name": "Gorillaz",
                "playcount": "173334985",
                "streamable": "0",
                "url": "https://www.last.fm/music/Gorillaz"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "982956",
                "mbid": "7fb57fba-a6ef-44c2-abab-2fa3bdee607e",
                "name": "Childish Gambino",
                "playcount": "54111939",
                "streamable": "0",
                "url": "https://www.last.fm/music/Childish+Gambino"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3784477",
                "mbid": "084308bd-1654-436f-ba03-df6697104e19",
                "name": "Green Day",
                "playcount": "191486003",
                "streamable": "0",
                "url": "https://www.last.fm/music/Green+Day"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1710145",
                "mbid": "012151a8-0f9a-44c9-997f-ebd68b5389f9",
                "name": "Imagine Dragons",
                "playcount": "85440640",
                "streamable": "0",
                "url": "https://www.last.fm/music/Imagine+Dragons"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "1297869",
                "mbid": "8e494408-8620-4c6a-82c2-c2ca4a1e4f12",
                "name": "Lorde",
                "playcount": "76314107",
                "streamable": "0",
                "url": "https://www.last.fm/music/Lorde"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "997026",
                "mbid": "25b7b584-d952-4662-a8b9-dd8cdfbfeb64",
                "name": "A$AP Rocky",
                "playcount": "48732470",
                "streamable": "0",
                "url": "https://www.last.fm/music/A$AP+Rocky"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "2976178",
                "mbid": "69ee3720-a7cb-4402-b48d-a02c366f2bcf",
                "name": "The Cure",
                "playcount": "160080692",
                "streamable": "0",
                "url": "https://www.last.fm/music/The+Cure"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "4472323",
                "mbid": "95e1ead9-4d31-4808-a7ac-32c3614c116b",
                "name": "The Killers",
                "playcount": "211585596",
                "streamable": "0",
                "url": "https://www.last.fm/music/The+Killers"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "2974470",
                "mbid": "d6e0e274-8e19-44ce-b5b2-52c12f8a674a",
                "name": "Led Zeppelin",
                "playcount": "191578475",
                "streamable": "0",
                "url": "https://www.last.fm/music/Led+Zeppelin"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "3825396",
                "mbid": "056e4f3e-d505-4dad-8ec1-d04f521cbb56",
                "name": "Daft Punk",
                "playcount": "212334330",
                "streamable": "0",
                "url": "https://www.last.fm/music/Daft+Punk"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "4019451",
                "mbid": "f59c5520-5f46-4d2c-b2c4-822eabf53419",
                "name": "Linkin Park",
                "playcount": "299550825",
                "streamable": "0",
                "url": "https://www.last.fm/music/Linkin+Park"
            },
            {
                "image": [
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "small"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "medium"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "large"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "extralarge"
                    },
                    {
                        "#text": "https://lastfm-img2.akamaized.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
                        "size": "mega"
                    }
                ],
                "listeners": "487567",
                "mbid": "c6bfb05d-f570-46c8-98e1-e25441189770",
                "name": "Khalid",
                "playcount": "15759258",
                "streamable": "0",
                "url": "https://www.last.fm/music/Khalid"
            }
        ]
    }
}

The structure of the JSON response is:

  • A dictionary with a single artists key, containing:
    • an @attr key containing a number of attributes about the response.
    • an artist key containing a list of artist objects.

Let's look at the '@attr' (attributes) key by itself:

jprint(r.json()['artists']['@attr'])
{
    "page": "1",
    "perPage": "50",
    "total": "2901036",
    "totalPages": "58021"
}

There are almost three million total artists in the results of this API endpoint, and we're being showing the first 50 artists in a single 'page'. This technique of spreading the results over multiple pages is called pagination.

Working with Paginated Data

In order to build a dataset with many artists, we need to make an API request for each page and then put them together. We can control the pagination of our results using two optional parameters specified in the documentation:

  • limit: The number of results to fetch per page (defaults to 50).
  • page: Which page of the results we want to fetch.

Because the '@attrs' key gives us the total number of pages, we can use a while loop and iterate over pages until the page number is equal to the last page number.

We can also use the limit parameter to fetch more results in each page — we'll fetch 500 results per page so we only need to make ~6,000 calls instead of ~60,000.

Let's look at an example of how we would structure that code:

# initialize list for results
results = []

# set initial page and a high total number
page = 1
total_pages = 99999

while page > total_pages:
    # simplified request code for this example
    r = request.get("endpoint_url", params={"page": page})

    # append results to list
    results.append(r.json())

    # increment page
    page += 1

As we mentioned a moment ago, we need to make almost 6,000 calls to this end point, which means we need to think about rate limiting to comply with the Last.fm API's terms of service. Let's look at a few approaches.

Rate Limiting

Rate limiting is using code to limit the number of times per second that we hit a particular API. Rate limiting will make your code slower, but it's better than getting banned from using an API altogether.

The easiest way to perform rate limiting is to use Python time.sleep() function. This function accepts a float specifying a number of seconds to wait before proceeding.

For instance, the following code will wait one quarter of a second between the two print statements:

import time

print("one")
time.sleep(0.25)
print("two")

Because making the API call itself takes some time, we're likely to be making two or three calls per second, not the four calls per second that sleeping for 0.25s might suggest. This should be enough to keep us under Last.fm's threshold (if we were going to be hitting their API for a number of hours, we might choose an even slower rate).

Another technique that's useful for rate limiting is using a local database to cache the results of any API call, so that if we make the same call twice, the second time it reads it from the local cache. Imagine that as you are writing your code, you discover syntax errors and your loop fails, and you have to start again. By using a local cache, you have two benefits:

  1. You don't make extra API calls that you don't need to.
  2. You don't need to wait the extra time to rate limit when reading the repeated calls from the cache.

The logic that we could use to combine waiting with a cache looks like the below:

API Rate limiting workflow

Creating logic for a local cache is a reasonably complex task, but there's a great library called requests-cache which will do all of the work for you with only a couple of lines of code.

You can install requests-cache using pip:

pip install requests-cache

Then all we need to do is import the library and invoke the requests_cache.install_cache() function, and the library will transparently cache new API requests, and use the cache whenever we make a repeated call.

import requests_cache

requests_cache.install_cache()

The last thing we should consider is that our 6,000 requests will likely take about 30 minutes to make, and so we'll print some output in each loop so we can see where everything is at. We'll use an IPython display trick to clear the output after each run so things look neater in our notebook.

Let's get started!

import time
from IPython.core.display import clear_output

responses = []

page = 1
total_pages = 99999 # this is just a dummy number so the loop starts

while page < = total_pages:
    payload = {
        'method': 'chart.gettopartists',
        'limit': 500,
        'page': page
    }

    # print some output so we can see the status
    print("Requesting page {}/{}".format(page, total_pages))
    # clear the output to make things neater
    clear_output(wait = True)

    # make the API call
    response = lastfm_get(payload)

    # if we get an error, print the response and halt the loop
    if response.status_code != 200:
        print(response.text)
        break

    # extract pagination info
    page = int(response.json()['artists']['@attr']['page'])
    total_pages = int(response.json()['artists']['@attr']['totalPages'])

    # append response
    responses.append(response)

    # if it's not a cached result, sleep
    if not getattr(response, 'from_cache', False):
        time.sleep(0.25)

    # increment the page number
    page += 1</code>
Requesting page 5803/5803

The first time you run that code, it will take around half an hour. Because of the cache, the second time will be much quicker (likely less than a minute!)

Processing the Data

Let's use pandas to look at the data from the first response in our responses list:

import pandas as pd

r0 = responses[0]
r0_json = r0.json()
r0_artists = r0_json['artists']['artist']
r0_df = pd.DataFrame(r0_artists)
r0_df.head()
name playcount listeners mbid url streamable image
0 Lana Del Rey 232808939 1957174 b7539c32-53e7-4908-bda3-81449c367da6 https://www.last.fm/music/Lana+Del+Rey 0 [{'#text': 'https://lastfm-img2.akamaized.net/...
1 Billie Eilish 35520548 588883 https://www.last.fm/music/Billie+Eilish 0 [{'#text': 'https://lastfm-img2.akamaized.net/...
2 Post Malone 34942708 655052 https://www.last.fm/music/Post+Malone 0 [{'#text': 'https://lastfm-img2.akamaized.net/...
3 Taylor Swift 196907702 2290993 20244d07-534f-4eff-b4d4-930878889970 https://www.last.fm/music/Taylor+Swift 0 [{'#text': 'https://lastfm-img2.akamaized.net/...
4 Ariana Grande 124251766 1166180 f4fdbb4c-e4b7-47a0-b83b-d91bbfcfa387 https://www.last.fm/music/Ariana+Grande 0 [{'#text': 'https://lastfm-img2.akamaized.net/...

We can use list comprehension to perform this operation on each response from responses, giving us a list of dataframes, and then use the pandas.concat() function to turn the list of dataframes into a single dataframe.

Converting a list of lists into a pandas dataframe

frames = [pd.DataFrame(r.json()['artists']['artist']) for r in responses]
artists = pd.concat(frames)
artists.head()
name playcount listeners mbid url streamable image
0 Lana Del Rey 232808939 1957174 b7539c32-53e7-4908-bda3-81449c367da6 https://www.last.fm/music/Lana+Del+Rey 0 [{'#text': 'https://lastfm-img2.akamaized.net/...
1 Billie Eilish 35520548 588883 https://www.last.fm/music/Billie+Eilish 0 [{'#text': 'https://lastfm-img2.akamaized.net/...
2 Post Malone 34942708 655052 https://www.last.fm/music/Post+Malone 0 [{'#text': 'https://lastfm-img2.akamaized.net/...
3 Taylor Swift 196907702 2290993 20244d07-534f-4eff-b4d4-930878889970 https://www.last.fm/music/Taylor+Swift 0 [{'#text': 'https://lastfm-img2.akamaized.net/...
4 Ariana Grande 124251766 1166180 f4fdbb4c-e4b7-47a0-b83b-d91bbfcfa387 https://www.last.fm/music/Ariana+Grande 0 [{'#text': 'https://lastfm-img2.akamaized.net/...

Our next step will be to remove the image column, which contains URLs for artist images that aren't really helpful to us from an analysis standpoint.

artists = artists.drop('image', axis=1)
artists.head()
name playcount listeners mbid url streamable
0 Lana Del Rey 232808939 1957174 b7539c32-53e7-4908-bda3-81449c367da6 https://www.last.fm/music/Lana+Del+Rey 0
1 Billie Eilish 35520548 588883 https://www.last.fm/music/Billie+Eilish 0
2 Post Malone 34942708 655052 https://www.last.fm/music/Post+Malone 0
3 Taylor Swift 196907702 2290993 20244d07-534f-4eff-b4d4-930878889970 https://www.last.fm/music/Taylor+Swift 0
4 Ariana Grande 124251766 1166180 f4fdbb4c-e4b7-47a0-b83b-d91bbfcfa387 https://www.last.fm/music/Ariana+Grande 0

Now, let's get to know the data a little using DataFrame.info() and DataFrame.describe():

artists.info()
artists.describe()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 10500 entries, 0 to 499
Data columns (total 6 columns):
name          10500 non-null object
playcount     10500 non-null object
listeners     10500 non-null object
mbid          10500 non-null object
url           10500 non-null object
streamable    10500 non-null object
dtypes: object(6)
memory usage: 574.2+ KB
name playcount listeners mbid url streamable
count 10500 10500 10500 10500 10500 10500
unique 10000 9990 9882 7223 10000 1
top Clairo 4591789 2096985 https://www.last.fm/music/alt-J 0
freq 2 2 4 2813 2 10500

We were expecting about 3,000,000 artists but we only have 10,500. Of those, only 10,000 are unique (eg there are duplicates).

Let's let's look at the length of the list of artists across our list of response objects to see if we can better understand what has gone wrong.

artist_counts = [len(r.json()['artists']['artist']) for r in responses]
pd.Series(artist_counts).value_counts()
0       5783
500       19
1000       1
dtype: int64

It looks like only twenty of our requests had a list of responses - let's look at the first fifty in order and see if there's a pattern.

print(artist_counts[:50])
[500, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

It looks like after the first twenty responses, this API doesn't return any data — an undocumented limitation.

This is not the end of the world, since 10,000 artists is still a good amount of data. Let's get rid of the duplicates we detected earlier.

artists = artists.drop_duplicates().reset_index(drop=True)
artists.describe()
name playcount listeners mbid url streamable
count 10000 10000 10000 10000 10000 10000
unique 10000 9990 9882 7223 10000 1
top Säkert! 508566 30176 https://www.last.fm/music/Heinz+Goldblatt 0
freq 1 2 3 2750 1 10000

Augmenting the Data Using a Second Last.fm API Endpoint

In order to make our data more interesting, let's use another last.fm API endpoint to add some extra data about each artist.

Last.fm allows its users to create "tags" to categorize artists. By using the artist.getTopTags endpoint we can get the top tags from an individual artist.

Let's look at the response from that endpoint for one of our artists as an example:

r = lastfm_get({
    'method': 'artist.getTopTags',
    'artist':  'Lana Del Rey'
})

jprint(r.json())
{
    "toptags": {
        "@attr": {
            "artist": "Lana Del Rey"
        },
        "tag": [
            {
                "count": 100,
                "name": "female vocalists",
                "url": "https://www.last.fm/tag/female+vocalists"
            },
            {
                "count": 93,
                "name": "indie",
                "url": "https://www.last.fm/tag/indie"
            },
            {
                "count": 88,
                "name": "indie pop",
                "url": "https://www.last.fm/tag/indie+pop"
            },
            {
                "count": 80,
                "name": "pop",
                "url": "https://www.last.fm/tag/pop"
            },
            {
                "count": 67,
                "name": "alternative",
                "url": "https://www.last.fm/tag/alternative"
            },
            {
                "count": 14,
                "name": "american",
                "url": "https://www.last.fm/tag/american"
            },
            {
                "count": 13,
                "name": "dream pop",
                "url": "https://www.last.fm/tag/dream+pop"
            },
            {
                "count": 12,
                "name": "seen live",
                "url": "https://www.last.fm/tag/seen+live"
            },
            {
                "count": 10,
                "name": "singer-songwriter",
                "url": "https://www.last.fm/tag/singer-songwriter"
            },
            {
                "count": 10,
                "name": "trip-hop",
                "url": "https://www.last.fm/tag/trip-hop"
            },
            {
                "count": 7,
                "name": "cult",
                "url": "https://www.last.fm/tag/cult"
            },
            {
                "count": 7,
                "name": "sadcore",
                "url": "https://www.last.fm/tag/sadcore"
            },
            {
                "count": 7,
                "name": "legend",
                "url": "https://www.last.fm/tag/legend"
            },
            {
                "count": 6,
                "name": "Lana Del Rey",
                "url": "https://www.last.fm/tag/Lana+Del+Rey"
            },
            {
                "count": 6,
                "name": "chamber pop",
                "url": "https://www.last.fm/tag/chamber+pop"
            },
            {
                "count": 5,
                "name": "baroque pop",
                "url": "https://www.last.fm/tag/baroque+pop"
            },
            {
                "count": 4,
                "name": "female vocalist",
                "url": "https://www.last.fm/tag/female+vocalist"
            },
            {
                "count": 4,
                "name": "alternative pop",
                "url": "https://www.last.fm/tag/alternative+pop"
            },
            {
                "count": 4,
                "name": "Retro",
                "url": "https://www.last.fm/tag/Retro"
            },
            {
                "count": 3,
                "name": "art pop",
                "url": "https://www.last.fm/tag/art+pop"
            },
            {
                "count": 3,
                "name": "chillout",
                "url": "https://www.last.fm/tag/chillout"
            },
            {
                "count": 3,
                "name": "soul",
                "url": "https://www.last.fm/tag/soul"
            },
            {
                "count": 3,
                "name": "USA",
                "url": "https://www.last.fm/tag/USA"
            },
            {
                "count": 3,
                "name": "sexy",
                "url": "https://www.last.fm/tag/sexy"
            },
            {
                "count": 2,
                "name": "new york",
                "url": "https://www.last.fm/tag/new+york"
            },
            {
                "count": 2,
                "name": "rock",
                "url": "https://www.last.fm/tag/rock"
            },
            {
                "count": 2,
                "name": "hollywood sadcore",
                "url": "https://www.last.fm/tag/hollywood+sadcore"
            },
            {
                "count": 2,
                "name": "indie rock",
                "url": "https://www.last.fm/tag/indie+rock"
            },
            {
                "count": 2,
                "name": "trip hop",
                "url": "https://www.last.fm/tag/trip+hop"
            },
            {
                "count": 2,
                "name": "female",
                "url": "https://www.last.fm/tag/female"
            },
            {
                "count": 2,
                "name": "jazz",
                "url": "https://www.last.fm/tag/jazz"
            },
            {
                "count": 2,
                "name": "10s",
                "url": "https://www.last.fm/tag/10s"
            },
            {
                "count": 2,
                "name": "folk",
                "url": "https://www.last.fm/tag/folk"
            },
            {
                "count": 2,
                "name": "lana",
                "url": "https://www.last.fm/tag/lana"
            },
            {
                "count": 2,
                "name": "electronic",
                "url": "https://www.last.fm/tag/electronic"
            },
            {
                "count": 2,
                "name": "blues",
                "url": "https://www.last.fm/tag/blues"
            },
            {
                "count": 2,
                "name": "2010s",
                "url": "https://www.last.fm/tag/2010s"
            },
            {
                "count": 2,
                "name": "vintage",
                "url": "https://www.last.fm/tag/vintage"
            },
            {
                "count": 2,
                "name": "alternative rock",
                "url": "https://www.last.fm/tag/alternative+rock"
            },
            {
                "count": 2,
                "name": "overrated",
                "url": "https://www.last.fm/tag/overrated"
            },
            {
                "count": 2,
                "name": "retro pop",
                "url": "https://www.last.fm/tag/retro+pop"
            },
            {
                "count": 2,
                "name": "beautiful",
                "url": "https://www.last.fm/tag/beautiful"
            },
            {
                "count": 2,
                "name": "melancholic",
                "url": "https://www.last.fm/tag/melancholic"
            },
            {
                "count": 2,
                "name": "dark pop",
                "url": "https://www.last.fm/tag/dark+pop"
            },
            {
                "count": 1,
                "name": "Hollywood Pop",
                "url": "https://www.last.fm/tag/Hollywood+Pop"
            },
            {
                "count": 1,
                "name": "chill",
                "url": "https://www.last.fm/tag/chill"
            },
            {
                "count": 1,
                "name": "americana",
                "url": "https://www.last.fm/tag/americana"
            },
            {
                "count": 1,
                "name": "diva",
                "url": "https://www.last.fm/tag/diva"
            },
            {
                "count": 1,
                "name": "sad",
                "url": "https://www.last.fm/tag/sad"
            }
        ]
    }
}

We're really only interested in the tag names, and then only the most popular tags. Let's use list comprehension to create a list of the top three tag names:

tags = [t['name'] for t in r.json()['toptags']['tag'][:3]]
tags
['female vocalists', 'indie', 'indie pop']

And then we can use the str.join() method to turn the list into a string:

', '.join(tags)
'female vocalists, indie, indie pop'

Let's create a function that uses this logic to return a string of the most popular tag for any artist, which we'll use later to apply to every row in our dataframe.

Remember that this function will be used a lot in close succession, so we'll reuse our time.sleep() logic from earlier.

def lookup_tags(artist):
    response = lastfm_get({
        'method': 'artist.getTopTags',
        'artist':  artist
    })

    # if there's an error, just return nothing
    if response.status_code != 200:
        return None

    # extract the top three tags and turn them into a string
    tags = [t['name'] for t in response.json()['toptags']['tag'][:3]]
    tags_str = ', '.join(tags)

    # rate limiting
    if not getattr(response, 'from_cache', False):
        time.sleep(0.25)
    return tags_str

And let's test our function on another artist:

lookup_tags("Billie Eilish")
'pop, indie pop, indie'

Applying this function to our 10,000 rows will take just under an hour. So we know that things are actually progressing, we'll look to monitor the operation with output like we did before.

Unfortunately, manually printing output isn't an approach we can use when applying a function with the pandas Series.apply() method. Instead, we'll use the tqdm package which automates this.

from tqdm import tqdm
tqdm.pandas()

artists['tags'] = artists['name'].progress_apply(lookup_tags)
10

Let's look at the result of our operation:

artists.head()
name playcount listeners mbid url streamable tags
0 Lana Del Rey 232808939 1957174 b7539c32-53e7-4908-bda3-81449c367da6 https://www.last.fm/music/Lana+Del+Rey 0 female vocalists, indie, indie pop
1 Billie Eilish 35520548 588883 https://www.last.fm/music/Billie+Eilish 0 pop, indie pop, indie
2 Post Malone 34942708 655052 https://www.last.fm/music/Post+Malone 0 Hip-Hop, rap, trap
3 Taylor Swift 196907702 2290993 20244d07-534f-4eff-b4d4-930878889970 https://www.last.fm/music/Taylor+Swift 0 country, pop, female vocalists
4 Ariana Grande 124251766 1166180 f4fdbb4c-e4b7-47a0-b83b-d91bbfcfa387 https://www.last.fm/music/Ariana+Grande 0 pop, female vocalists, rnb

Finalizing and Exporting the Data

Before we export our data, we might like to sort the data so the most popular artists are at the top. So far we've just been storing data as text without converting any types:

artists.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10000 entries, 0 to 9999
Data columns (total 7 columns):
name          10000 non-null object
playcount     10000 non-null object
listeners     10000 non-null object
mbid          10000 non-null object
url           10000 non-null object
streamable    10000 non-null object
tags          10000 non-null object
dtypes: object(7)
memory usage: 547.0+ KB

Let's start by converting the listeners and playcount columns to numeric.

artists[["playcount", "listeners"]] = artists[["playcount", "listeners"]].astype(int)

Now, let's sort by number of listeners

artists = artists.sort_values("listeners", ascending=False)
artists.head(10)
name playcount listeners mbid url streamable tags
23 Coldplay 364107739 5429555 cc197bad-dc9c-440d-a5b5-d52ba2e14234 https://www.last.fm/music/Coldplay 0 rock, alternative, britpop
10 Radiohead 507682999 4778856 a74b1b7f-71a5-4011-9441-d0b5e4122711 https://www.last.fm/music/Radiohead 0 alternative, alternative rock, rock
24 Red Hot Chili Peppers 298043491 4665823 8bfac288-ccc5-448d-9573-c33ea2aa5c30 https://www.last.fm/music/Red+Hot+Chili+Peppers 0 rock, alternative rock, alternative
12 Rihanna 204114198 4618838 db36a76f-4cdf-43ac-8cd0-5e48092d2bae https://www.last.fm/music/Rihanna 0 pop, rnb, female vocalists
35 Eminem 204081058 4569194 b95ce3ff-3d05-4e87-9e01-c97b66af13d4 https://www.last.fm/music/Eminem 0 rap, Hip-Hop, Eminem
45 The Killers 211585596 4472323 95e1ead9-4d31-4808-a7ac-32c3614c116b https://www.last.fm/music/The+Killers 0 indie, rock, indie rock
7 Kanye West 250533444 4449534 164f0d73-1234-4e2c-8743-d77bf2191051 https://www.last.fm/music/Kanye+West 0 Hip-Hop, rap, hip hop
28 Nirvana 226060468 4320593 9282c8b4-ca0b-4c6b-b7e3-4f7762dfc4d6 https://www.last.fm/music/Nirvana 0 Grunge, rock, alternative
57 Muse 349264164 4123148 fd857293-5ab8-40de-b29e-55a69d4e4d0f https://www.last.fm/music/Muse 0 alternative rock, rock, alternative
6 Queen 197850122 4084524 420ca290-76c5-41af-999e-564d7c71f1a7 https://www.last.fm/music/Queen 0 classic rock, rock, 80s

Finally, we can export our dataset as a CSV file.

artists.to_csv('artists.csv', index=False)

Next Steps

In this tutorial we built a dataset using the Last.fm API while learning how to use Python to:

  • How to authenticate with an API using an API key
  • How to use pagination to collect larger responses from an API endpoint
  • How to use rate-limiting to stay within the guidelines of an API.

If you'd like to extend your learning, you might like to:

  • Complete our interactive Dataquest APIs and scraping course, which you can start for free.
  • Explore the other API endpoints in the Lasts.fm API.
  • Try working with some data from this list of Free Public APIs.
Celeste Grupman

About the author

Celeste Grupman

Celeste is the Director of Operations at Dataquest. She is passionate about creating affordable access to high-quality skills training for students across the globe.

Learn data skills for free

Headshot Headshot

Join 1M+ learners

Try free courses