Download
Download single tracks by ISRC or URL, YouTube and SoundCloud audio, and expand Spotify playlists.
Download
Download audio from four sources: a single track (by ISRC or Spotify/Deezer URL), a YouTube video, a SoundCloud track, and a Spotify playlist (expanded to a track list you then download per ISRC).
Download a track
https://music.jakeypri.me/downloadAuth requiredResolve a track either by ISRC or by a Spotify/Deezer track URL, and stream back the audio file. Spotify URLs are resolved to their ISRC and matched on Deezer; link.deezer.com short links are resolved automatically.
isrcurl.urlisrc. URL-encode it. Playlist URLs are rejected, see playlists.quality128128, 320, or flac.Response
200 with a binary audio stream.
Content-Type:audio/mpegfor128/320,audio/flacforflac.Content-Disposition:attachmentwith a filename derived as<artist> - <name>.<ext>.
HQ results (anything other than the default 128) are cached for 24 hours, so a repeat request for the same ISRC and quality is served from cache. A HEAD /download is also supported (same params) and returns just the headers.
Quality notes
- The default is
128whenqualityis omitted, not320. flacis not available for every track. When it is not, the response is404 { "error": "Requested quality not available for this track." }. Fall back to320in that case.
Errors
400{ "error": "Either url or isrc parameter is required" }when neither is supplied.400{ "error": "Invalid quality. Must be 128, 320, or flac" }.400{ "error": "Invalid ISRC. Must be 12 characters." }.400playlist URL supplied (use/playlistdownload).404{ "error": "Track not found for this ISRC" }/"Track not found"/"Requested quality not available for this track."500on a server-side failure. Some Spotify resolution errors include extrahintordetailsfields.
Examples
# By ISRC, HQ
curl -L "https://music.jakeypri.me/download?isrc=USRC17607839&quality=320&key=YOUR_KEY" \
-o track.mp3
# By Spotify URL (URL-encoded)
curl -L "https://music.jakeypri.me/download?url=https%3A%2F%2Fopen.spotify.com%2Ftrack%2F69kOkLUCkxIZYexIgSG8rq&key=YOUR_KEY" \
-o track.mp3import { writeFile } from "fs/promises";
const res = await fetch(
"https://music.jakeypri.me/download?isrc=USRC17607839&quality=320",
{ headers: { "X-API-Key": "YOUR_KEY" } }
);
if (res.status === 404) {
// quality unavailable or track not found — inspect res.json().error
}
await writeFile("track.mp3", Buffer.from(await res.arrayBuffer()));Download YouTube audio
https://music.jakeypri.me/ytAuth requiredurlyoutube.com/watch, youtu.be, shorts, or embed). URL-encode it. The video ID is parsed out of the URL.200 with an audio/mpeg stream, Content-Disposition: attachment named <video title>.mp3. Cached for 24 hours by video ID. Errors: 400 { "error": "URL is required" }, 400 { "error": "Invalid YouTube URL" }, 500 { "error": "Failed to download YouTube audio" }.
curl -L "https://music.jakeypri.me/yt?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdQw4w9WgXcQ&key=YOUR_KEY" \
-o audio.mp3const url = encodeURIComponent("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
const res = await fetch(`https://music.jakeypri.me/yt?url=${url}`, {
headers: { "X-API-Key": "YOUR_KEY" },
});Download SoundCloud audio
https://music.jakeypri.me/soundcloudAuth requiredurlsoundcloud.com, m., www., or on.soundcloud.com). URL-encode it.200 with an audio/mpeg stream, Content-Disposition: attachment named <artist - title>.mp3 (falls back to the track id). Cached for 24 hours by track id. Errors: 400 { "error": "URL is required" }, 400 { "error": "Invalid SoundCloud URL" }, 500 { "error": "Failed to download SoundCloud audio" }.
curl -L "https://music.jakeypri.me/soundcloud?url=https%3A%2F%2Fsoundcloud.com%2Fartist%2Ftrack&key=YOUR_KEY" \
-o audio.mp3const url = encodeURIComponent("https://soundcloud.com/artist/track");
const res = await fetch(`https://music.jakeypri.me/soundcloud?url=${url}`, {
headers: { "X-API-Key": "YOUR_KEY" },
});Expand a Spotify playlist
https://music.jakeypri.me/playlistdownloadAuth requiredThis endpoint does not return audio. It expands a Spotify playlist into a list of tracks (ISRC, name, artist) that are resolvable on Deezer. To actually download the playlist, call this once, then loop over the returned tracks and call /download for each ISRC.
urlResponse
200 with a JSON object. Only tracks resolvable on Deezer are included, so found may be lower than totalTracks.
{
"totalTracks": 50,
"found": 48,
"tracks": [
{ "isrc": "USQX91300108", "name": "Get Lucky", "artist": "Daft Punk" }
]
}totalTracksfoundtracks).tracksisrc, name, and artist. Feed each isrc to /download.Errors
400{ "error": "URL is required" }.400{ "error": "Only Spotify playlists are supported at this time" }.400invalid playlist, with ahintfield.500{ "error": "Failed to process playlist" }.
Two-step download flow
# 1. Expand the playlist to a track list
curl "https://music.jakeypri.me/playlistdownload?url=https%3A%2F%2Fopen.spotify.com%2Fplaylist%2F37i9dQZF1DXcBWIGoYBM5M&key=YOUR_KEY"
# 2. For each isrc in the response, download it
curl -L "https://music.jakeypri.me/download?isrc=USQX91300108&quality=320&key=YOUR_KEY" -o "track.mp3"import { writeFile } from "fs/promises";
const KEY = "YOUR_KEY";
const playlist = encodeURIComponent(
"https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
);
// 1. Expand
const list = await fetch(
`https://music.jakeypri.me/playlistdownload?url=${playlist}`,
{ headers: { "X-API-Key": KEY } }
).then((r) => r.json());
// 2. Download each track by ISRC
for (const t of list.tracks) {
const res = await fetch(
`https://music.jakeypri.me/download?isrc=${t.isrc}&quality=320`,
{ headers: { "X-API-Key": KEY } }
);
if (!res.ok) continue; // skip tracks that fail to resolve
await writeFile(`${t.artist} - ${t.name}.mp3`, Buffer.from(await res.arrayBuffer()));
}