A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://developer.spotify.com/documentation/web-api/howtos/web-app-profile below:

Display your Spotify profile data in a web app

Display your Spotify profile data in a web app

This guide creates a simple client-side application that uses the Spotify Web API to get user profile data. We'll show both TypeScript and JavaScript code snippets, make sure to use the code that is correct for your application.

External applications can use the Spotify Web API to retrieve Spotify content, such as song data, album data and playlists. However, in order to access user-related data with the Spotify Web API, an application must be authorized by the user to access that particular information.

Prerequisites

To work through this guide you'll need:

Set up your account

Login to the Spotify Developer Dashboard. If necessary, accept the latest Developer Terms of Service to complete your account set up.

Creating a Spotify app

We will need to register a new app to generate valid credentials - we'll use these credentials later to perform API calls. Follow the apps guide to learn how to create an app and generate the necessary credentials.

Once you've created your app, make a note of your client_id.

Creating a new project

This app uses Vite as a development server. We'll scaffold a new project with the Vite create command and use their default template to give us a basic app:


_10

npm create vite@latest spotify-profile-demo -- --template vanilla-ts


Select y when it prompts you to install Vite.

Change directory to the new app directory that Vite just created and start the development server:


_10

cd spotify-profile-demo


The default Vite template creates some files that we won't need for this demo, so you can delete all of the files in ./src/ and ./public/

Creating the user interface

This demo is going to be a single page application that runs entirely in the browser. We're going to replace the provided index.html file with a simple HTML page that constitutes the user interface to display the user's profile data.

Start by deleting the content of the index.html file and replacing it with a html and head tag that references a TypeScript/JavaScript file (src/script.ts, or src/script.js, we'll create this file later).


_16

<meta charset="utf-8">

_16

<title>My Spotify Profile</title>

_16

<script src="src/script.ts" type="module"></script>

_16

<!-- Note- We're referring directly to the TypeScript file,

_16

and we're using the `type="module"` attribute.

_16

Vite will transpile our TypeScript to JavaScript

_16

so that it can run in the browser. -->


Inside the body, we'll add some markup to display the profile data:


_13

<h1>Display your Spotify profile data</h1>

_13

<section id="profile">

_13

<h2>Logged in as <span id="displayName"></span></h2>

_13

<span id="avatar"></span>

_13

<li>User ID: <span id="id"></span></li>

_13

<li>Email: <span id="email"></span></li>

_13

<li>Spotify URI: <a id="uri" href="#"></a></li>

_13

<li>Link: <a id="url" href="#"></a></li>

_13

<li>Profile Image: <span id="imgUrl"></span></li>


Some elements in this block have id attributes. We'll use these to replace the element's text with the data we fetch from the Web API.

Calling the Web API

We're going to use the Web API to get the user's profile data. We'll use the authorization code flow with PKCE to get an access token, and then use that token to call the API.

How it works

Create a src/script.ts or src/script.js file and add the following code:


_26

const clientId = "your-client-id-here"; // Replace with your client id

_26

const code = undefined;

_26

redirectToAuthCodeFlow(clientId);

_26

const accessToken = await getAccessToken(clientId, code);

_26

const profile = await fetchProfile(accessToken);

_26

async function redirectToAuthCodeFlow(clientId: string) {

_26

// TODO: Redirect to Spotify authorization page

_26

async function getAccessToken(clientId: string, code: string) {

_26

// TODO: Get access token for code

_26

async function fetchProfile(token: string): Promise<any> {

_26

// TODO: Call Web API

_26

function populateUI(profile: any) {

_26

// TODO: Update UI with profile data


This is the outline of our application.

On the first line there is a clientId variable - you'll need to set this variable to the client_id of the Spotify app you created earlier.

The code now needs to be updated to redirect the user to the Spotify authorization page. To do this, let's write the redirectToAuthCodeFlow function:


_35

export async function redirectToAuthCodeFlow(clientId: string) {

_35

const verifier = generateCodeVerifier(128);

_35

const challenge = await generateCodeChallenge(verifier);

_35

localStorage.setItem("verifier", verifier);

_35

const params = new URLSearchParams();

_35

params.append("client_id", clientId);

_35

params.append("response_type", "code");

_35

params.append("redirect_uri", "http://127.0.0.1:5173/callback");

_35

params.append("scope", "user-read-private user-read-email");

_35

params.append("code_challenge_method", "S256");

_35

params.append("code_challenge", challenge);

_35

document.location = `https://accounts.spotify.com/authorize?${params.toString()}`;

_35

function generateCodeVerifier(length: number) {

_35

let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

_35

for (let i = 0; i < length; i++) {

_35

text += possible.charAt(Math.floor(Math.random() * possible.length));

_35

async function generateCodeChallenge(codeVerifier: string) {

_35

const data = new TextEncoder().encode(codeVerifier);

_35

const digest = await window.crypto.subtle.digest('SHA-256', data);

_35

return btoa(String.fromCharCode.apply(null, [...new Uint8Array(digest)]))


In this function, a new URLSearchParams object is created, and we add the client_id, response_type, redirect_uri and scope parameters to it. The scope parameter is a list of permissions that we're requesting from the user. In this case, we're requesting the user-read-private and user-read-email scopes - these are the scopes that allow us to fetch the user's profile data.

The redirect_uri parameter is the URL that Spotify will redirect the user back to after they've authorized the application. In this case, we're using a URL that points to our local Vite dev server.

You need to make sure this URL is listed in the Redirect URIs section of your Spotify Application Settings in your Developer Dashboard.

You will also notice that we are generating PKCE verifier and challenge data, we're using this to verify that our request is authentic. We're using local storage to store the verifier data, which works like a password for the token exchange process.

To prevent the user from being stuck in a redirect loop when they authenticate, we need to check if the callback contains a code parameter. To do this, the first three lines of code in the file are modified like this:


_11

const clientId = "your_client_id";

_11

const params = new URLSearchParams(window.location.search);

_11

const code = params.get("code");

_11

redirectToAuthCodeFlow(clientId);

_11

const accessToken = await getAccessToken(clientId, code);

_11

const profile = await fetchProfile(accessToken);


In order to make sure that the token exchange works, we need to write the getAccessToken function.


_19

export async function getAccessToken(clientId: string, code: string): Promise<string> {

_19

const verifier = localStorage.getItem("verifier");

_19

const params = new URLSearchParams();

_19

params.append("client_id", clientId);

_19

params.append("grant_type", "authorization_code");

_19

params.append("code", code);

_19

params.append("redirect_uri", "http://127.0.0.1:5173/callback");

_19

params.append("code_verifier", verifier!);

_19

const result = await fetch("https://accounts.spotify.com/api/token", {

_19

headers: { "Content-Type": "application/x-www-form-urlencoded" },

_19

const { access_token } = await result.json();


In this function, we load the verifier from local storage and using both the code returned from the callback and the verifier to perform a POST to the Spotify token API. The API uses these two values to verify our request and it returns an access token.

Now, if we run npm run dev, and navigate to http://127.0.0.1:5173 in a browser, we'll be redirected to the Spotify authorization page. If we authorize the application, we'll be redirected back to our application, but no data will be fetched and displayed.

To fix this, we need to update the fetchProfile function to call the Web API and get the profile data. Update the fetchProfile function:


_10

async function fetchProfile(token: string): Promise<any> {

_10

const result = await fetch("https://api.spotify.com/v1/me", {

_10

method: "GET", headers: { Authorization: `Bearer ${token}` }

_10

return await result.json();


In this function, a call is made to https://api.spotify.com/v1/me using the browser's Fetch API to get the profile data. The Authorization header is set to Bearer ${token}, where token is the access token that we got from the https://accounts.spotify.com/api/token endpoint.

If we add a console.log statement to the calling code we can see the profile data that is returned from the API in the browser's console:


_10

const profile = await fetchProfile(token);

_10

console.log(profile); // Profile data logs to console


Finally, we need to update the populateUI function to display the profile data in the UI. To do this, we'll use the DOM to find our HTML elements and update them with the profile data:


_15

function populateUI(profile: any) {

_15

document.getElementById("displayName")!.innerText = profile.display_name;

_15

if (profile.images[0]) {

_15

const profileImage = new Image(200, 200);

_15

profileImage.src = profile.images[0].url;

_15

document.getElementById("avatar")!.appendChild(profileImage);

_15

document.getElementById("id")!.innerText = profile.id;

_15

document.getElementById("email")!.innerText = profile.email;

_15

document.getElementById("uri")!.innerText = profile.uri;

_15

document.getElementById("uri")!.setAttribute("href", profile.external_urls.spotify);

_15

document.getElementById("url")!.innerText = profile.href;

_15

document.getElementById("url")!.setAttribute("href", profile.href);

_15

document.getElementById("imgUrl")!.innerText = profile.images[0]?.url ?? '(no profile image)';


You can now run your code by running npm run dev in the terminal and navigating to http://127.0.0.1:5173 in your browser.

At the moment, even though we're using TypeScript, we don't have any type safety around the data being returned from the Web API. To improve this, we can create a UserProfile interface to describes the data that we expect to be returned from the API. Adding an interface will define the shape of the object that we're expecting, this will make using the data type-safe and will allow for type prompts while coding, making a more pleasant developer experience if you extend this project in future.

To do this, create a new file called types.d.ts in the src folder and add the following code:


_23

interface UserProfile {

_23

display_name: string;

_23

filter_enabled: boolean,

_23

filter_locked: boolean

_23

external_urls: { spotify: string; };

_23

followers: { href: string; total: number; };


We can now update our calling code to expect these types:


_10

async function fetchProfile(token: string): Promise<UserProfile> {

_10

function populateUI(profile: UserProfile) {


You can view and fork the final code for this demo on GitHub: Get User Profile Repository.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4