Apple Music Top Playlists API. Top playlists, on request.
Most played playlists chart by country. We handle the proxies, blocks and platform changes.
Apple Music Top Playlists API at a glance
Returns Apple Music's chart of the most played playlists in a country's store, top first, a page at a time, with each playlist's rank and curator. Each row also has the title, Apple's description and note, full-size cover, track count, whether Apple's editors or an outside curator make it, when it last changed and its audio formats. Pick the store with country, the US by default.
GET /v1/applemusic/top_playlists
- 1 credit per page, $0.75–$1.97 per 1,000 pages
- 13 typed fields null when unknown
- 50 most played playlists per page, Apple Music's own chart order (1 = most played)
- 100 credits free when you sign up, no card, so you can build before you spend
Send one request. Get up to 50 most played playlists back.
Copy the request in your language, or hand it to your agent. Sign up for an API key and your first 100 credits are free.
$ npm install socialtapconst params = new URLSearchParams({
country: "US",
});
const res = await fetch(`https://socialtap.dev/v1/applemusic/top_playlists?${params}`, {
headers: { "x-api-key": process.env.SOCIALTAP_API_KEY ?? "" },
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
const { data, page, meta } = body;
console.log(data, meta.credits_charged);import os
import requests
res = requests.get(
"https://socialtap.dev/v1/applemusic/top_playlists",
params={"country": "US"},
headers={"x-api-key": os.environ["SOCIALTAP_API_KEY"]},
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
data, page, meta = body["data"], body["page"], body["meta"]
print(data, meta["credits_charged"])require "json"
require "net/http"
uri = URI("https://socialtap.dev/v1/applemusic/top_playlists")
uri.query = URI.encode_www_form('country' => 'US')
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = ENV.fetch("SOCIALTAP_API_KEY")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(req) }
body = JSON.parse(res.body)
raise "#{body["error"]["code"]}: #{body["error"]["message"]}" unless res.is_a?(Net::HTTPSuccess)
pp body["data"]
puts body["meta"]["credits_charged"]<?php
$query = http_build_query([
'country' => 'US',
]);
$ch = curl_init('https://socialtap.dev/v1/applemusic/top_playlists?' . $query);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['x-api-key: ' . getenv('SOCIALTAP_API_KEY')],
]);
$body = json_decode(curl_exec($ch), true);
if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) >= 400) {
throw new RuntimeException($body['error']['code'] . ': ' . $body['error']['message']);
}
print_r($body['data']);
echo $body['meta']['credits_charged'], PHP_EOL;package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"os"
)
func main() {
q := url.Values{}
q.Set("country", "US")
req, err := http.NewRequest("GET", "https://socialtap.dev/v1/applemusic/top_playlists?"+q.Encode(), nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("x-api-key", os.Getenv("SOCIALTAP_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
var body struct {
Data json.RawMessage `json:"data"`
Page json.RawMessage `json:"page"`
Meta map[string]any `json:"meta"`
Error *struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
log.Fatal(err)
}
if body.Error != nil {
log.Fatalf("%s: %s", body.Error.Code, body.Error.Message)
}
fmt.Println(string(body.Data), body.Meta["credits_charged"])
}curl 'https://socialtap.dev/v1/applemusic/top_playlists?country=US' \
-H "x-api-key: $SOCIALTAP_API_KEY"{
"data": [
{
"approximate_fields": [],
"description": "Music has been an essential part of any holiday celebration for centuries. This playlist honors that history, collecting old chestnuts, new classics, and future sing-along staples to soundtrack your next Christmas. Trim the tree, open the presents, and serve up some eggnog as pop…",
"id": "pl.b0e04e25887741ea845e1d5c88397fd4",
"is_collaborative": false,
"metrics": {
"post_count": 100
},
"owner": {
"avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features126/v4/dc/03/16/dc031679-6f1e-5ec0-cd81-17edf19c66c2/7e2c3f93-9d73-41c2-9cec-841a2240173a.png/1080x1080bb.jpg",
"display_name": "Holiday",
"id": null,
"is_verified": null,
"url": "https://music.apple.com/us/curator/holiday/976439540",
"username": null
},
"platform": "applemusic",
"platform_specific": {
"applemusic": {
"audio_traits": [],
"band": null,
"curator_id": "976439540",
"editorial_kind": null,
"editorial_sub_kind": null,
"editorial_summary": "The songs that define the season.",
"frequency": null,
"is_chart": false,
"is_collaborative": false,
"is_live": null,
"is_subscription_required": null,
"last_modified_at": "2026-10-23T19:16:13Z",
"media_kind": null,
"playlist_type": "editorial",
"rank": 1,
"station_kind": null,
"storefront": "us"
}
},
"platform_type": "playlist",
"thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Features112/v4/d1/a8/45/d1a84579-ce57-5a1f-1334-e6c417605020/befc39eb-584c-4681-92b0-16c913f1230a.png/4320x1080cc.jpg",
"title": "Essential Christmas",
"type": "playlist",
"unknown_fields": [],
"url": "https://music.apple.com/us/playlist/essential-christmas/pl.b0e04e25887741ea845e1d5c88397fd4"
},
{
"approximate_fields": [],
"description": "This playlist tracks what’s happening from the heart of the country scene to its outer edges. Find fan favorites you already love next to breakout stars and emerging voices. Topping the list this week is HARDY with “By God,” a track off the country star’s just-released EP Sides. …",
"id": "pl.87bb5b36a9bd49db8c975607452bfa2b",
"is_collaborative": false,
"metrics": {
"post_count": 73
},
"owner": {
"avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features/v4/a0/3c/32/a03c3207-70b9-5a3d-28d9-430e2a1891cc/2775cb3b-a652-41ea-91f5-e28fe0d43bde.png/1080x1080bb.jpg",
"display_name": "Apple Music Country",
"id": null,
"is_verified": null,
"url": "https://music.apple.com/us/curator/apple-music-country/976439534",
"username": null
},
"platform": "applemusic",
"platform_specific": {
"applemusic": {
"audio_traits": [],
"band": null,
"curator_id": "976439534",
"editorial_kind": null,
"editorial_sub_kind": null,
"editorial_summary": "“By God” is HARDY at his most inspirational.",
"frequency": null,
"is_chart": false,
"is_collaborative": false,
"is_live": null,
"is_subscription_required": null,
"last_modified_at": "2026-10-30T23:33:21Z",
"media_kind": null,
"playlist_type": "editorial",
"rank": 2,
"station_kind": null,
"storefront": "us"
}
},
"platform_type": "playlist",
"thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Features/v4/ea/0a/1d/ea0a1d2e-6b0b-e3b7-673f-2534fb354b22/dd2db469-90b2-4cd7-9c7b-83809965c0f9.png/1080x1080SC.DN02.jpg?l=en-US",
"title": "Today’s Country",
"type": "playlist",
"unknown_fields": [],
"url": "https://music.apple.com/us/playlist/todays-country/pl.87bb5b36a9bd49db8c975607452bfa2b"
},
{
"approximate_fields": [],
"description": "From the alt vanguard to modern vets, straightforward to left-field, R&B Now captures where the genre is now and points the way to where it’s going. In 2026, that meant another breakout year for Kehlani, the moment years of consistent artistry finally converted into mainstream do…",
"id": "pl.9987b58cfa9747328b3fe9b974e2b797",
"is_collaborative": false,
"metrics": {
"post_count": 50
},
"owner": {
"avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features/v4/47/94/31/479431e2-12bd-c03e-48bd-1022fe74b1b2/b8395439-127c-43b1-bea6-ebc3433a0e9c.png/1080x1080bb.jpg",
"display_name": "Apple Music R&B",
"id": null,
"is_verified": null,
"url": "https://music.apple.com/us/curator/apple-music-r-b/976439551",
"username": null
},
"platform": "applemusic",
"platform_specific": {
"applemusic": {
"audio_traits": [],
"band": null,
"curator_id": "976439551",
"editorial_kind": null,
"editorial_sub_kind": null,
"editorial_summary": "In 2026, Kehlani’s “Folded” told us everything we needed to hear.",
"frequency": null,
"is_chart": false,
"is_collaborative": false,
"is_live": null,
"is_subscription_required": null,
"last_modified_at": "2026-11-04T17:39:22Z",
"media_kind": null,
"playlist_type": "editorial",
"rank": 3,
"station_kind": null,
"storefront": "us"
}
},
"platform_type": "playlist",
"thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Features/v4/59/98/c9/5998c9a4-61d1-c40a-c790-f525acc95b40/4b4be703-911f-4917-8199-12762b25551d.png/1080x1080SC.DN02.jpg?l=en-US",
"title": "R&B Now: Best of 2026",
"type": "playlist",
"unknown_fields": [],
"url": "https://music.apple.com/us/playlist/r-b-now-best-of-2026/pl.9987b58cfa9747328b3fe9b974e2b797"
}
],
"page": {
"has_more": true,
"next_cursor": "c1.EXAMPLE_CURSOR",
"next_cursor_expires_at": "2026-10-26T12:00:00Z",
"end_reason": null
},
"meta": {
"request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
"platform": "applemusic",
"source": "api",
"is_cached": false,
"credits_charged": 1,
"latency_ms": 384,
"fetched_at": "2026-10-25T12:00:00Z",
"input": null,
"credits_remaining": 9999,
"client_request_id": null,
"warnings": []
}
}import { SocialTap } from "socialtap";
const client = new SocialTap(); // apiKey defaults to process.env.SOCIALTAP_API_KEY
const res = await client.applemusic.topPlaylists.list({ country: "US" });
console.log(res.data);
console.log(res.credits.charged, res.meta.request_id);import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
public class Main {
public static void main(String[] args) throws Exception {
String query = "country=" + encode("US");
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://socialtap.dev/v1/applemusic/top_playlists?" + query))
.header("x-api-key", System.getenv("SOCIALTAP_API_KEY"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
// An error is {"error": {"code", "message", ...}}; success is {data, meta}, meta.credits_charged its price.
if (response.statusCode() >= 400) throw new RuntimeException(response.body());
System.out.println(response.body());
}
static String encode(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
}using System.Text.Json;
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("x-api-key", Environment.GetEnvironmentVariable("SOCIALTAP_API_KEY"));
var query = string.Join("&",
"country=" + Uri.EscapeDataString("US"));
var res = await http.GetAsync("https://socialtap.dev/v1/applemusic/top_playlists?" + query);
using var body = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
if (!res.IsSuccessStatusCode)
{
var error = body.RootElement.GetProperty("error");
throw new Exception($"{error.GetProperty("code")}: {error.GetProperty("message")}");
}
Console.WriteLine(body.RootElement.GetProperty("data"));
Console.WriteLine(body.RootElement.GetProperty("meta").GetProperty("credits_charged"));// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }, serde_json = "1"
use std::env;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let res = reqwest::blocking::Client::new()
.get("https://socialtap.dev/v1/applemusic/top_playlists")
.query(&[("country", "US")])
.header("x-api-key", env::var("SOCIALTAP_API_KEY")?)
.send()?;
let ok = res.status().is_success();
let body: serde_json::Value = res.json()?;
if !ok {
return Err(format!("{}: {}", body["error"]["code"], body["error"]["message"]).into());
}
println!("{} {}", body["data"], body["meta"]["credits_charged"]);
Ok(())
}200 OK · GET https://socialtap.dev/v1/applemusic/top_playlistsLong arrays and strings are shortened here. Real responses are complete.Docs One schema on 6 platforms.
The response reference lists every field, its type and when it is null. See the full schema.
Null means unknown
A field Apple Music doesn't show is null, never zero or an empty string, so a real zero always means zero.
No input needed
Every parameter is optional: the plain request returns the default list.
Write one parser
Apple Music, TikTok, Instagram and 3 more platforms answer in these fields, so the code that reads one reads them all.
platformstring- Platform ID (tiktok, youtube, facebook, …).
idstring- Platform-native playlist ID (string): TikTok's playlist (mix) or collection ID, YouTube's list ID (PL…), Facebook's video list ID.
urlstring- Canonical playlist URL.
typestring- playlist: a list its owner curates and orders (TikTok playlists, YouTube playlists, Facebook playlists and series); collection: posts an account saved from any creator into a named public folder (TikTok collections). New values may be added; treat unknown values as playlist.
platform_typestring- The platform's own label, lowercase (mix, collection, playlist, series, podcast, …).
titlestring- Name its owner gave it.
descriptionstring- Description as plain text; null when it has none or the platform shows none (TikTok).
ownerobject- The account that curates it (for a collection, the account that saved the posts, not their authors). Where a platform's curators are not accounts (Apple Music), what it states of them: a name, perhaps a page and a picture, with id and username null, and every field null when it names no one.
Live data from 33 platforms.
What teams build with the Apple Music Top Playlists API.
Track the most played playlists each day
Compare a playlist's rank across countries
See which curators lead a market
Build a pitch list of top playlists
Good to know before you build.
- platform_specific.applemusic.rank is the row's place in the chart, top first, and stays the same whatever limit you ask for. Apple publishes no play or follower counts, so the rank is all the chart says.
- Apple serves about 200 rows per chart, fewer in a few small stores, and the walk then ends with page.end_reason end: that is the whole chart.
- owner.id is null because a curator isn't an artist, the only account this platform's endpoints take. platform_specific.applemusic.curator_id holds Apple's ID for it, null on the playlists Apple Music signs itself, which name no curator beyond owner.display_name.
- Charts differ by store, and platform_specific.applemusic.storefront says which store answered. A store's titles can be in its own language: lang asks for another where Apple offers it, and a language it doesn't offer gets the store's own.
- A playlist has no release date, so this chart takes no since or until. platform_specific.applemusic.last_modified_at says when each last changed.
- The Apple Music Top Tracks API charts songs and music videos, and the Apple Music Top Albums API albums.
- When Apple's catalog API fails, the top of the chart comes from Apple's RSS feed and ends the walk with platform_limit: the curator, description, track count and everything in platform_specific but the store and rank are null, and audio_traits is [] and listed in unknown_fields. The feed has no languages, so a request with lang fails rather than answer in another.
1 credit per page. Failed requests are free.
Buy credits once and spend them on any endpoint, on any platform.
| Source | Price per successful page | Per 1,000 pages |
|---|---|---|
Platform API api | 1 credit | $0.75–$1.97 |
- Cache hits are free.
- Credits from packs and top-ups never expire.
- A monthly plan's credits are spent first, and what is left of them ends at each renewal.
- Prices exclude tax: sales tax is added at checkout where it applies.
- Outside the US, plans and packs are sold to businesses: checkout asks for your VAT, GST or other business tax ID.
Questions about the Apple Music Top Playlists API.
More in the API reference.
How much does the Apple Music Top Playlists API cost?
How do I get the next page?
See what's on the list right now.
Run it in the playground, or copy the request into your code.
- No credit card
- Failed requests are free
- Works on all 218 endpoints