This guide helps you extract a developer token dynamically from Apple Music's public site (https://beta.music.apple.com) and use it to access metadata for songs or albums via Apple’s internal amp-api
.
The unofficial method of scraping tokens from the Apple Music website is not sanctioned by Apple and is subject to break without notice if the website's structure is updated. For production applications, the official developer token method is strongly recommended due to its stability and reliability.
The process can be broken down into two main steps:
-
Find the Core JavaScript File: The initial step is to fetch the HTML of the Apple Music beta website (
https://beta.music.apple.com
). Within this HTML, we look for a reference to a specific JavaScript file, typically named in a pattern likeindex-legacy-[hash].js
. This file contains the necessary logic and, more importantly, the token. -
Extract the Token: Once the JavaScript file is identified and its content is fetched, a regular expression is used to find a string that matches the pattern of a JSON Web Token (JWT). This token is the key to making authorized requests to a specific, undocumented AMP API endpoint.
export async function getToken(): Promise<string> {
// Step 1: Fetch the main page to find the JS file
const mainPageURL = 'https://beta.music.apple.com';
const mainPageResponse = await fetch(mainPageURL);
if (!mainPageResponse.ok) {
throw new Error(
`Failed to fetch main page: ${mainPageResponse.statusText}`
);
}
const mainPageBody = await mainPageResponse.text();
// Find the index-legacy JS URI using regex
const jsFileRegex = /\/assets\/index-legacy-[^/]+\.js/;
const indexJsUri = mainPageBody.match(jsFileRegex)?.[0];
if (!indexJsUri) {
throw new Error('Index JS file not found');
}
// Step 2: Fetch the JS file to extract the token
const jsFileURL = mainPageURL + indexJsUri;
const jsFileResponse = await fetch(jsFileURL);
if (!jsFileResponse.ok) {
throw new Error(
`Failed to fetch JS file: ${jsFileResponse.statusText}`
);
}
const jsFileBody = await jsFileResponse.text();
// Extract the token using regex
const tokenRegex = /eyJh[^"]+/;
const token = jsFileBody.match(tokenRegex)?.[0];
if (!token) {
throw new Error('Token not found in JS file');
}
return token;
}
The extracted token can then be used to make requests to the https://amp-api.music.apple.com
endpoint. This is a different endpoint than the official Apple Music API.
Here's how you can use this token to fetch song metadata:
export async function getSongMeta(
urlMeta: URLMeta,
token: string
): Promise<any | null> { // Replace 'any' with a proper type definition for the song response
const url = `https://amp-api.music.apple.com/v1/catalog/${urlMeta.storefront}/${urlMeta.urlType}/${urlMeta.id}`;
const queryParams = new URLSearchParams({
include: 'albums,explicit',
extend: 'extendedAssetUrls',
l: '',
});
const response = await fetch(`${url}?${queryParams.toString()}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Origin': 'https://music.apple.com',
},
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const songResponse = await response.json();
// Assuming the response has a 'data' array of songs
for (const song of songResponse.data) {
if (song.id === urlMeta.id) {
return song;
}
}
return null; // No matching song found
}
export interface URLMeta {
storefront: string;
urlType: string;
id: string;
}
storefront
: This is the two-letter country code for the Apple Music store you want to query. Examples includeus
for the United States,in
for India, andgb
for Great Britain.urlType
: This specifies the type of content you are looking for. Common types aresongs
,albums
,artists
, andplaylists
.id
: This is the unique identifier for the specific song, album, artist, or playlist.
const songMeta: URLMeta = {
storefront: 'us',
urlType: 'songs',
id: '1452434833'
};