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

social-dl

v1.3.6

Published

Social media downloader with direct extractors and Spotify metadata with confidence-matched track audio

Readme

SOCIAL MEDIA SCRAPPER ⚉

brought to you by CRYSNOVA_AI

social-dl — The last downloader you'll ever need

Direct social-media downloader for YouTube, TikTok, Facebook, Instagram, Twitter/X, Pinterest, CapCut, and Spotify links. Spotify metadata is read from public embeds; full audio uses a separately matched source, never a Spotify stream.

npm License Node

social-dl direct media downloader

Why social-dl?

| Capability | social-dl | Proxy downloader API | |---|---:|---:| | Direct CDN extraction | Yes | No | | Depends on a third-party API staying online | No | Yes | | API key required | No | Often | | Open source | No — proprietary | Varies |

Install

npm install social-dl

social-dl uses the verified yt-dlp executable bundled with the package, including on Android/Termux. If yt-dlp cannot retrieve a source, social-dl tries Cobalt-compatible and PrexzyAPIs fallbacks. Node.js 18 or newer is required. License and third-party notices for the bundled release are included under licenses/yt-dlp/.

Pinned yt-dlp engine

yt-dlp is vendored, pinned, and verified: it ships inside the package instead of being resolved at runtime.

| Platform | Vendored binary | Integrity | |---|---|---| | Linux | bin/yt-dlp | verified against SHA2-256SUMS | | macOS | bin/yt-dlp_macos | verified against SHA2-256SUMS | | Windows | bin/yt-dlp.exe | verified against SHA2-256SUMS |

The pinned release is recorded in licenses/yt-dlp/VERSION, in the official licenses/yt-dlp/SHA2-256SUMS, and in the YTDLP_VERSION / YTDLP_SHA256 constants of src/core/binary.js — all three are kept in sync.

The runtime never downloads or discovers yt-dlp. It does not fetch from GitHub, search PATH, read YTDLP_PATH, use yt-dlp-exec, or install an external downloader. It resolves the executable vendored in this package and fails loudly if that file is missing.

Keeping yt-dlp current

Updates are prepared automatically and reviewed by a human — never silently applied:

  • .github/workflows/update-ytdlp.yml runs on the first day of every month, and on demand through workflow_dispatch.
  • It resolves the latest stable yt-dlp release, rejecting drafts, prereleases, and tags that are not in YYYY.MM.DD form.
  • Every binary is verified against that release's official SHA2-256SUMS before anything is replaced, and the official LICENSE and THIRD_PARTY_LICENSES.txt are refreshed from the same tag.
  • The verified result is pushed to an automation/yt-dlp-<version> branch and opened as a reviewable pull request. Nothing is committed to main automatically, and the pull request is never auto-merged.

Run the same update locally with:

node scripts/update-ytdlp.mjs

The updater uses only Node.js built-ins, writes every file atomically (temp file plus rename) so a failed run cannot leave a partial binary behind, preserves the executable bit on the Linux and macOS binaries, and is idempotent — re-running it against an already-pinned release leaves the working tree untouched.

Termux setup

pkg update
pkg install nodejs ffmpeg python
npm install -g social-dl
npx social-dl doctor

If a platform blocks the network, retry with a permitted cookie export or proxy rather than repeatedly hammering the provider. Keep yt-dlp and FFmpeg current through the package release; social-dl pins its bundled yt-dlp engine for reproducible behavior.

CLI

npx social-dl https://youtu.be/BJs3DBrMTSc
npx social-dl https://youtu.be/BJs3DBrMTSc --mp3 -o audio.m4a
npx social-dl https://facebook.com/share/r/xxx/ --json
npx social-dl https://www.tiktok.com/@user/video/123 --no-watermark
npx social-dl https://www.instagram.com/reel/CODE/ --cookies ~/cookies.txt -o instagram.mp4
npx social-dl https://www.tiktok.com/@user/video/123 --cookies-from-browser chrome -o tiktok.mp4
npx social-dl https://open.spotify.com/track/0wf9rSX8ds3yEI2gf2QdPs -o dreams.mp3
npx social-dl https://open.spotify.com/track/0wf9rSX8ds3yEI2gf2QdPs --json
npx social-dl doctor

Easy format and quality selection

Every supported platform uses the same command shape. mp4 is the default video mode; mp3 uses FFmpeg to extract audio when the source provides a compatible audio stream.

# Interactive Termux-friendly menu
npx social-dl

# Direct commands
npx social-dl "URL" --format mp4 --quality best -o video.mp4
npx social-dl "URL" --format mp4 --quality 720p -o video.mp4
npx social-dl "URL" --format mp3 -o audio.mp3
npx social-dl "URL" --format mp4 --quality 720p --safe -o video.mp4

# Equivalent shorthand for MP3
npx social-dl "URL" --mp3 -o audio.mp3

--quality best|720p|480p applies to video downloads when the provider exposes selectable formats. --safe/--safe-mode adds conservative yt-dlp pacing (3–6 second sleeps and a 5M rate limit); it reduces request pressure but is not an anti-bot bypass. Use cookies or a permitted proxy for content requiring authentication.

Spotify track links

social-dl reads Spotify track metadata directly from Spotify's public embed page and does not depend on spotify.xwolf.space, a Spotify bearer token, or a developer account. For a full-length MP3, it searches the bundled yt-dlp-supported source using the Spotify title, artist, and duration, and saves only a sufficiently close candidate. Audio retrieval tries the primary yt-dlp path, the package's generic fallbacks, then the existing youtubeMp3Save() path; if that returns native M4A/Opus audio, FFmpeg converts it to MP3. The result keeps platform: "spotify" for the input link and includes matchedSource/audioSource so developers can see where the audio actually came from. If the match is uncertain, it raises NoConfidentMatchError (NO_CONFIDENT_MATCH) and downloads nothing. This is not a full-track Spotify stream; it can fail if the external result is unavailable or requires permitted cookies. A previewUrl, when Spotify supplies one, is only preview metadata and is not used as a substitute for the full track.

import { spotifyMetadata, spotifyDl, spotifySave } from 'social-dl/spotify';

const metadata = await spotifyMetadata('https://open.spotify.com/track/0wf9rSX8ds3yEI2gf2QdPs');
const resolved = await spotifyDl(metadata.originalUrl); // metadata + validated match
await spotifySave(metadata.originalUrl, './dreams.mp3');

Run npx social-dl doctor to verify Node.js, FFmpeg, the pinned yt-dlp binary/version, and provider reachability before troubleshooting a download. Use npx social-dl maintenance for the interactive engine update and safe cache reset menu; reset never deletes downloaded media. --format mp3 requires FFmpeg; if a platform only exposes a ready-made media file, social-dl keeps the provider’s native media instead of pretending it can convert it. --json shows normalized metadata and available formats before saving, while --no-watermark requests a no-watermark variant when the provider supports one.

For login-required Instagram or TikTok posts, pass an exported cookie file with --cookies path/to/cookies.txt or use --cookies-from-browser chrome, firefox, edge, or brave. YouTube may reject datacenter IPs; doctor reports this as BOT_DETECTED.

Library

import { universalDl, universalSave, universalStream } from 'social-dl';

const data = await universalDl('https://youtu.be/BJs3DBrMTSc');
await universalSave('https://youtu.be/BJs3DBrMTSc', './video.mp4');

Platform-specific library examples

Every platform also exposes its own xxxDl() and xxxSave() functions. Each Dl() call returns normalized metadata and direct CDN formats; each Save() call downloads the selected format.

Facebook

import { facebookDl, facebookSave } from 'social-dl/facebook';

const facebook = await facebookDl('https://www.facebook.com/reel/1234567890/');
await facebookSave('https://www.facebook.com/reel/1234567890/', './facebook.mp4', 'HD');

YouTube video

import { youtubeDl, youtubeSave } from 'social-dl/youtube';

const youtube = await youtubeDl('https://youtu.be/BJs3DBrMTSc');
await youtubeSave('https://youtu.be/BJs3DBrMTSc', './youtube.mp4', '720p');

YouTube audio

import { youtubeMp3Dl, youtubeMp3Save } from 'social-dl/ytmp3';

const audio = await youtubeMp3Dl('https://youtu.be/BJs3DBrMTSc');
await youtubeMp3Save('https://youtu.be/BJs3DBrMTSc', './audio.m4a');

Instagram

import { instagramDl, instagramSave } from 'social-dl/instagram';

const instagram = await instagramDl('https://www.instagram.com/reel/CODE/', { cookiesPath: './cookies.txt' });
await instagramSave('https://www.instagram.com/reel/CODE/', './instagram.mp4', 'best', { cookiesPath: './cookies.txt' });

TikTok

import { tiktokDl, tiktokSave } from 'social-dl/tiktok';

const tiktok = await tiktokDl('https://www.tiktok.com/@user/video/1234567890123456789', { cookiesFromBrowser: 'chrome' });
await tiktokSave('https://www.tiktok.com/@user/video/1234567890123456789', './tiktok.mp4', 'NOWM', { cookiesFromBrowser: 'chrome' });

Twitter/X

import { twitterDl, twitterSave } from 'social-dl/twitter';

const tweet = await twitterDl('https://x.com/user/status/1851234567890');
await twitterSave('https://x.com/user/status/1851234567890', './twitter.mp4');

Pinterest

import { pinterestDl, pinterestSave } from 'social-dl/pinterest';

const pin = await pinterestDl('https://www.pinterest.com/pin/1234567890/');
await pinterestSave('https://www.pinterest.com/pin/1234567890/', './pinterest.mp4');

CapCut

import { capcutDl, capcutSave } from 'social-dl/capcut';

const template = await capcutDl('https://www.capcut.com/template-detail/1234567890');
await capcutSave('https://www.capcut.com/template-detail/1234567890', './capcut.mp4');

Express/Next.js streaming

const { stream, contentType, filename } = await universalStream(url);
res.setHeader('Content-Type', contentType);
res.setHeader('Content-Disposition', `inline; filename="${filename}"`);
Readable.fromWeb(stream).pipe(res);

[NEW] Spotify

import { spotifyDl, spotifySave } from 'social-dl/spotify';

const template = await spotifyDl('https://open.spotify.com/track/0wf9rSX8ds3yEI2gf2QdPs');
await spotifySave('https://open.spotify.com/track/0wf9rSX8ds3yEI2gf2QdPs', './spotify.mp3');

Platforms

| Platform | Example | |---|---| | Facebook | https://www.facebook.com/reel/1234567890/ | | YouTube | https://youtu.be/BJs3DBrMTSc | | Instagram | https://www.instagram.com/reel/CODE/ | | TikTok | https://www.tiktok.com/@user/video/123 | | Twitter/X | https://x.com/user/status/123 | | Pinterest | https://www.pinterest.com/pin/1234567890/ | | CapCut | https://www.capcut.com/template-detail/1234567890 | | YouTube audio | Same YouTube URLs with { audioOnly: true } or --mp3 | | Spotify track | https://open.spotify.com/track/0wf9rSX8ds3yEI2gf2QdPs (MP3; match-checked) |

API reference

  • universalDl(url, { audioOnly, quality, cookiesPath, cookiesFromBrowser }) — return normalized direct-CDN formats.
  • universalSave(url, destination, { audioOnly, quality, noWatermark, cookiesPath, cookiesFromBrowser, safeMode }) — save a selected format. safeMode: true enables conservative pacing for yt-dlp. audioOnly: true is the library equivalent of --format mp3.
  • The shared CLI works across YouTube, TikTok, Facebook, Instagram, Twitter/X, Pinterest, and CapCut. Video quality and MP3 conversion depend on the formats and FFmpeg support available for each source.
  • universalStream(url, options) — return a Web ReadableStream for piping.
  • spotifyMetadata(url) — read public Spotify embed metadata for a track, album, artist, or playlist without using the WOLF API.
  • spotifyDl(url, options) — return track metadata plus a conservative separate-source audio match; formats is empty because the match is not a Spotify CDN URL.
  • spotifySave(url, destination, quality, options) — download the validated track match as MP3; may require FFmpeg and/or permitted source cookies.
  • doctor({ log }) — test provider reachability, Node, FFmpeg, and the bundled yt-dlp engine.
  • npx social-dl maintenance — interactively update the yt-dlp engine or reset only generated cache/cookie state; downloaded media is preserved.
  • Every platform exports xxxDl() and xxxSave().

Fallback Credits

social-dl uses multiple fallback services to improve download reliability:

  • PrexzyAPIs.com
  • Cobalt-compatible endpoints

Fallbacks are used when the primary yt-dlp path cannot retrieve media. Third-party services may be unavailable or change behavior.

Set SOCIAL_DL_PROXY to use a proxy for the primary yt-dlp request. The fallback services do not require this variable. For YouTube bot checks, provide an exported Netscape cookie file with --cookies path/to/youtube-cookies.txt, use --cookies-from-browser chrome, or set SOCIAL_DL_YOUTUBE_COOKIES / SOCIAL_DL_YOUTUBE_COOKIES_FROM_BROWSER. social-dl tries multiple yt-dlp YouTube clients before using Cobalt and Prexzy; third-party services can still be unavailable or block the source.

Support the creator

If social-dl helps your projects, support development through any of these options:

Bank transfer (Nigeria)

  • Bank: First Bank Nigeria
  • Account name: CRYSTAL-LEVI UZOUKWU
  • Account number: 3230171045

Telegram Stars

Use the bot donation shortcut: @CODYEBOT — Donate. You can also reach @crysnovax or @plogme.

USDT

  • Network: BNB Smart Chain (BEP-20)
  • Address: 0xa1140712e9a1d459fc32c7d2f7e33e18790db835

Confirm that your wallet is set to BEP-20 / BNB Smart Chain before sending. Run npx social-dl support to print these details in the terminal.

Scan to support

USDT BEP-20 donation QR code

If the QR image does not render, open the direct image link: https://cdn.crysnova.qzz.io/files/1790796246940-eede6a21-3ee8-45d3-94ad-2fcd0fa82525.jpeg.

Contact and community

For support, updates, and community help:

Run npx social-dl support to print donation and contact links in the terminal.

Error handling

Handle BotDetectedError for provider anti-automation blocks, PrivateError for login/private content, NotFoundError for missing media, NoConfidentMatchError when a Spotify audio match is not strong enough, and UnsupportedError for unsupported URLs.

Demo

Demo video coming in 1.0.0 — npx becomes available after this 0.9.0 pre-launch.

Release checklist

Before publishing a new npm version:

npm test
npm pack --dry-run
npx social-dl doctor

The package requires Node.js 18 or newer. MP3 conversion requires FFmpeg. Provider availability can change independently of social-dl, so login-required or blocked sources should be tested with permitted cookies or a proxy.

License

Proprietary license. See LICENSE.

created and maintained by crysnovax • @plogme please this has no promotional intent or unofficial bridge of any sort. do not missus this package.