npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

spotdl-api

v1.0.0

Published

A powerful spotDL wrapper for Node.js to search, download, and sync Spotify tracks, albums, and playlists.

Readme

spotdl-api

A robust, fully-typed Node.js wrapper for spotdl (spotDL).

This package automatically downloads and manages the correct standalone spotdl executable for the host operating system during installation. It eliminates the need for a global Python or spotDL/ffmpeg dependency chain (ffmpeg is still required at runtime for audio conversion).

Installation

npm install spotdl-api

Usage Guide

The API is fully Promise-based and returns strictly typed objects.

1. Fetching Track/Album/Playlist Metadata

The save method resolves any spotdl query — a track, album, playlist, or artist URL, or free-text search — into full song metadata without downloading anything.

import spotdl from 'spotdl-api';

async function fetchMetadata() {
  const songs = await spotdl.save('https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC');

  console.log(songs[0].name); // Never Gonna Give You Up
  console.log(songs[0].artists); // ['Rick Astley']
  console.log(songs[0].duration); // 213
}

JSON Output Structure Example:

{
  "name": "Never Gonna Give You Up",
  "artists": ["Rick Astley"],
  "artist": "Rick Astley",
  "album_name": "Whenever You Need Somebody",
  "duration": 213,
  "year": 1987,
  "track_number": 1,
  "song_id": "4uLU6hMCjMI75M1A2tKUQC",
  "isrc": "GBARL9300135",
  "cover_url": "https://i.scdn.co/image/...",
  "url": "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC"
}

2. Looking Up a Single Song

getSongInfo is a convenience wrapper around save for a single query, returning just the first match.

import spotdl from 'spotdl-api';

const song = await spotdl.getSongInfo('The Weeknd - Blinding Lights');
console.log(song?.album_name);

3. Downloading Tracks with Progress Tracking

The download method downloads and transcodes audio, providing real-time progress callbacks for every song in the query.

import spotdl from 'spotdl-api';

async function downloadTrack() {
  await spotdl.download(
    'https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC',
    (progress) => {
      // Example: { song: 'Rick Astley - Never Gonna Give You Up', message: 'Downloading', percent: 70, status: 'downloading' }
      console.log(`${progress.song}: ${progress.message} (${progress.percent}%)`);
    },
    { format: 'mp3', output: '{artists} - {title}.{output-ext}' }
  );
}

4. Downloading Albums and Playlists

Any query type — track, album, playlist, or artist URL — works the same way, and can be mixed in a single call.

import spotdl from 'spotdl-api';

await spotdl.download([
  'https://open.spotify.com/playlist/37i9dQZF1E8UXBoz02kGID',
  'The Weeknd - Blinding Lights',
]);

5. Global Options (authentication, providers, cookies)

Pass a second argument to the SpotDl constructor to apply options to every call automatically — no need to repeat them via args each time.

import { SpotDl } from 'spotdl-api';

const spotdl = new SpotDl(undefined, {
  clientId: 'your-spotify-client-id',       // optional: spotDL ships public demo credentials by default
  clientSecret: 'your-spotify-client-secret',
  cookieFile: './cookies.txt',              // enables higher-bitrate YouTube Music audio
  audioProviders: ['youtube-music'],
  lyricsProviders: ['genius', 'musixmatch'],
  threads: 4,
  restrict: 'ascii',                        // sanitize output filenames
});

6. Resolving Direct Audio-Provider URLs

Skip the download entirely and get the raw, playable audio URL(s) resolved from the configured audio provider — useful for proxying or handing off to a media player.

import spotdl from 'spotdl-api';

const urls = await spotdl.getDirectUrl('https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC');
console.log(urls[0]); // https://...

7. Typed Errors

Failures are classified into specific error subclasses so callers can branch on why spotdl failed instead of parsing stderr themselves.

import spotdl, { NoResultsFoundError, SpotifyAuthError, FFmpegNotFoundError, NetworkError } from 'spotdl-api';

try {
  await spotdl.getSongInfo('some obscure query');
} catch (err) {
  if (err instanceof NoResultsFoundError) {
    // skip and move on
  } else if (err instanceof NetworkError) {
    // retry later
  }
  throw err;
}

8. Syncing a Local Folder to a Playlist

createSyncFile snapshots a query into a .spotdl file; sync then downloads new songs and removes ones no longer present in the source, keeping a local folder mirrored to a playlist or album over time.

import spotdl from 'spotdl-api';

await spotdl.createSyncFile(
  'https://open.spotify.com/playlist/37i9dQZF1E8UXBoz02kGID',
  './my-playlist.sync.spotdl'
);

// later, on a schedule:
await spotdl.sync('./my-playlist.sync.spotdl', (progress) => {
  console.log(`${progress.song}: ${progress.message}`);
});

9. Re-embedding Metadata

Refresh tags, cover art, and lyrics on already-downloaded files without re-downloading them.

import spotdl from 'spotdl-api';

await spotdl.embedMetadata(['./Rick Astley - Never Gonna Give You Up.mp3']);

10. Cancelling In-Flight Requests

Every method that spawns spotdl accepts an AbortSignal via options.signal.

import spotdl from 'spotdl-api';

const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);

await spotdl.download(url, undefined, { signal: controller.signal });

11. Batch Metadata Lookups with Bounded Concurrency

Fetches metadata for many queries at once without spawning unlimited processes. Each query resolves independently — one failure doesn't sink the batch.

import spotdl from 'spotdl-api';

const results = await spotdl.batchSave(queries, { concurrency: 3, delayMs: 250 });

for (const r of results) {
  if (r.status === 'fulfilled') console.log(r.query, r.value[0]?.name);
  else console.warn(r.query, r.reason.message);
}

API Reference

  • new SpotDl(binaryPath?: string, globalOptions?: GlobalOptions) Creates a wrapper instance. globalOptions (Spotify auth, audio/lyrics providers, etc.) apply to every call made through it.

  • spotdl.version(): Promise<string> Returns the version string of the underlying spotdl binary.

  • spotdl.save(queries: string | string[], options?: SaveOptions): Promise<Song[]> Resolves one or more queries into full track metadata (spotdl save --save-file -). A single query can expand into many songs (album/playlist/artist).

  • spotdl.getSongInfo(query: string, options?: SearchOptions): Promise<Song | undefined> Convenience wrapper around save for a single query, returning its first match.

  • spotdl.getDirectUrl(queries: string | string[], options?: SpotDlOptions): Promise<string[]> Resolves the direct, playable audio-provider URL(s) for one or more queries without downloading.

  • spotdl.download(queries: string | string[], onProgress?: (progress: DownloadProgress) => void, options?: DownloadOptions): Promise<void> Downloads and transcodes audio for one or more queries, emitting per-song progress events.

  • spotdl.createSyncFile(queries: string | string[], saveFile: string, options?: DownloadOptions): Promise<void> Creates a .spotdl sync file for the given query, ready to be passed to sync.

  • spotdl.sync(saveFile: string, onProgress?: (progress: DownloadProgress) => void, options?: SyncOptions): Promise<void> Downloads new songs and removes stale ones to keep a local folder in sync with a .spotdl file.

  • spotdl.embedMetadata(files: string[], options?: SpotDlOptions): Promise<void> Re-embeds metadata into already-downloaded audio files (spotdl meta).

  • spotdl.batchSave(queries: string[], options?: BatchOptions): Promise<BatchResult<Song[]>[]> Runs save over many queries with bounded concurrency; each query resolves independently as fulfilled or rejected.

  • spotdl.exec(args: string[], signal?: AbortSignal): Promise<string> Executes spotdl with arbitrary arguments and returns raw stdout.

License

MIT