Open-source project
scdl-org/scdl avatar
scdl-org/scdl

scdl: a yt-dlp wrapper for SoundCloud downloads with real ID3 tags

Soundcloud Music Downloader

4,126 stars401 forksPythonGPL-2.0

At a glance

What is it?
scdl is a Python command line tool that downloads SoundCloud tracks, playlists and user libraries, then writes Title, Artist, Album and cover art into the files with mutagen. Version 3 is a wrapper around yt-dlp, and the README says development is not active.
Who is it for?
scdl fits people who want tagged local copies of SoundCloud libraries and who are comfortable passing extra flags through --yt-dlp-args when a SoundCloud change breaks something. It is a poor fit if you need an actively developed downloader with new features, since the README states development is not active and new features will likely not be merged.
Can I use it commercially?
Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 41 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What scdl does that a plain yt-dlp command does not

SoundCloud URLs are not uniform. The same site holds single tracks, sets, user pages, likes, reposts and comments, and each of those needs a different traversal to produce a complete list of audio files. scdl's job is to detect which kind of link you handed it and then walk the right collection. Its feature list names the cases explicitly: all songs from a user, all songs and reposts, one playlist, all playlists from a user, a user's favorites, and only the tracks that are new since the last run.

The second job is metadata. A downloaded SoundCloud file often arrives with a filename that carries little structure and tags that are missing or wrong. scdl sets Title, Artist, Album and Artwork through mutagen, and it can create playlist files when it downloads a playlist. That combination, collection traversal plus tagging, is the reason to pick it over calling yt-dlp directly for a one-off track. If you only ever download a single song, the wrapper adds nothing you could not get from the underlying tool.

The audience is narrow and practical: people archiving their own likes, DJs pulling a label's uploads, anyone who wants a folder that a music player will index without manual retagging. It is a command line tool, with no server component and no web interface described in the README.

How version 3 works: a thin layer over yt-dlp with patches

The README is direct about the architecture. As of version 3, the script is a wrapper around yt-dlp with some defaults and patches for backwards compatibility. The dependency list in pyproject.toml confirms it: yt-dlp with the curl-cffi extra is a runtime dependency, alongside soundcloud-v2 for API access, mutagen for tagging and docopt-ng for the command line parser.

That layering explains several design decisions. The --yt-dlp-args option forwards a string of custom arguments straight to yt-dlp, which means the escape hatch for anything scdl does not expose is the upstream tool's own flag set. The README also states that new features will likely not be merged, especially if they can be covered with --yt-dlp-args. In other words, the maintainers treat scdl as a compatibility and convenience layer, not as a download engine.

The package declares requires-python >=3.10.0, and the project metadata lists classifiers up to Python 3.12 while the ruff configuration still targets py39. The mypy configuration ignores errors in scdl.patches, which is consistent with carrying patched behaviour that does not need to satisfy the same typing rules as the rest of the code. The entry point is scdl = "scdl.scdl:_main", so the installed command and the module path are the same name.

Installing scdl and downloading your first tagged track

The README lists two system requirements: python3 and ffmpeg. ffmpeg is what yt-dlp uses to convert or remux audio, so a machine without it will fail partway through a download rather than at startup. The README points to a wiki page titled Installation Instruction for the install steps, and the package is published as scdl on PyPI, so an install from the index is the expected path.

Install it into an isolated environment and confirm the command resolves:

bash
pip install scdl
scdl --version

If the version prints a 2.x number, you have the 2021 PyPI release rather than the 3.x wrapper. The repository's pyproject.toml declares version 3.0.8, so check that what you installed matches the code you intend to run.

Download a single track by passing its URL to -l. The README gives this exact example:

bash
scdl -l https://soundcloud.com/jumpstreetpsy/low-extender

You should end up with an audio file in the current directory with Title, Artist, Album and Artwork tags set by mutagen. To pull a whole playlist instead, use a sets URL:

bash
scdl -l https://soundcloud.com/pandadub/sets/the-lost-ship

For a library you intend to keep in sync, the archive file is the mechanism worth learning first. It records track IDs so later runs skip what is already present:

bash
scdl -l https://soundcloud.com/pandadub/sets/the-lost-ship --download-archive archive.txt -c

The -c flag continues when a downloaded file already exists, and --download-archive keeps the ID list. The README also documents a separate --sync archive.txt mode that compares an archive file against a playlist and downloads or removes changed tracks, which is the closest thing here to mirroring a playlist. Downloading your own likes requires an authentication token, and the README shows the form scdl me -f. A configuration file is left at ~/.config/scdl/scdl.cfg if you prefer to set options once rather than per invocation.

Where scdl breaks, and the maintenance picture

The README's status section is the first thing to read before adopting anything here. It states that development is not active and that new features will likely not be merged. Bug reports and fixes are welcome, but the direction of the project is closed. The last push to the repository was on 2026-08-20, and the most recent release listed is v2.4.0 from 2021-12-28, which predates the 3.x rewrite described in the README and the 3.0.8 version in pyproject.toml. Anyone pinning to a tagged release is pinning to the old architecture, not the wrapper.

Because the download path runs through yt-dlp and SoundCloud's own API, scdl inherits every breakage those two produce. A change in how SoundCloud serves streams, or a yt-dlp release that alters extraction, can stop downloads until one of the dependencies updates. The --yt-dlp-args option is the intended remedy, and the README's framing of it as the answer to most feature requests tells you where the maintainers expect fixes to land.

Some options carry their own caveats. --flac only works if the original file is lossless quality, so on the common lossy upload it does nothing. --hidewarnings is documented with the phrase use with precaution. --addtimestamp is marked deprecated in favour of --name-format. And --strict-playlist aborts an entire playlist download if a single track fails, which is the opposite of what most archive jobs want; without it, you get a partial playlist and no clear signal that something was skipped.

The wrong-tool case is straightforward. If you need a service that tracks SoundCloud changes for you, or a maintained tool with a roadmap, scdl is not it. It is also not a way around access controls: downloading likes requires a token you supply yourself.

How scdl differs from yt-dlp on its own

The honest alternative is yt-dlp itself, and the difference is not about download capability. yt-dlp already handles SoundCloud URLs and already supports metadata embedding and archive files. What it does not do is decide for you that a user page means all uploads, that a likes page means favorites, or that a playlist should produce a playlist file alongside the tracks. scdl encodes those SoundCloud-specific conventions and adds the tagging defaults that make a downloaded folder readable by a player without further work.

The trade-off runs the other way too. yt-dlp releases far more often and its extraction fixes land upstream first. If SoundCloud changes something on a Tuesday, the yt-dlp release is where the fix appears, and scdl's value depends on that dependency being current. Because scdl pins yt-dlp with a minimum version rather than vendoring it, a fresh install pulls recent extraction code, which softens the maintenance gap considerably. But the wrapper logic around it, the link detection and the tagging defaults, is what stops receiving new work.

For a scripted pipeline where you already control yt-dlp flags and output templates, adding scdl is an extra dependency that mostly duplicates what you have. For an interactive user who wants their likes folder tagged correctly with one command, the wrapper earns its place.

Licence and the cost of staying on scdl

scdl is GPL-2.0, as stated in the repository's LICENSE file and in the classifier in pyproject.toml. If you redistribute it or ship a modified version, the GPL's terms apply to that distribution, and the same is true if you bundle it into a larger distributed product. Running it locally for your own downloads is a different situation. This is a description of what the licence says, not legal advice; if the tool is going into something you ship, read the GPL text and talk to someone qualified.

Upgrade cost is low in the mechanical sense and high in the strategic one. The dependency set is small and ordinary, and pyproject.toml pins only minimum versions, so pip install scdl picks up current yt-dlp. There is no database, no service to migrate and no configuration schema that changes often; the config file at ~/.config/scdl/scdl.cfg is plain and the command line surface is stable enough that the README's examples still read as current usage.

The strategic cost is that improvements to the wrapper are unlikely to arrive. If your workflow depends on a behaviour scdl does not implement, the README's own answer is --yt-dlp-args, which means the fix lives in your invocation rather than in the project. Budget for that: keep the yt-dlp arguments you rely on written down next to the command you run, because they are now part of your setup rather than something upstream will maintain for you.

Editorial conclusion

scdl fits people who want tagged local copies of SoundCloud libraries and who are comfortable passing extra flags through --yt-dlp-args when a SoundCloud change breaks something. It is a poor fit if you need an actively developed downloader with new features, since the README states development is not active and new features will likely not be merged. Before adopting it, check that python3 and ffmpeg are present, run scdl --version to confirm you have the 3.x wrapper rather than the 2.x release on PyPI from 2021, and test one track with scdl -l on a URL you own.

Frequently asked questions

How can I download SoundCloud songs with metadata using scdl?

Pass the track or playlist URL to the -l option, for example scdl -l https://soundcloud.com/jumpstreetpsy/low-extender. scdl sets Title, Artist, Album and Artwork tags on the downloaded file through mutagen.

What is scdl from scdl-org?

It is a SoundCloud music downloader written in Python. As of version 3 it is a wrapper around yt-dlp with defaults and patches for backwards compatibility, and it can download tracks, playlists, user uploads, reposts and likes.

What do I need installed before running scdl?

The README lists python3 and ffmpeg as the system requirements. The package itself is published on PyPI as scdl, and the README points to a wiki page for installation instructions.

Why does scdl ask for a client_id or an auth token?

The command line exposes --client-id and --auth-token options, and the README shows that downloading your own likes with scdl me -f requires an authentication token. You supply the token yourself; scdl does not provide one.

How do I avoid re-downloading tracks I already have with scdl?

Use --download-archive with a file path, which keeps track of track IDs and skips files already downloaded, and add -c to continue when a downloaded file already exists. There is also a --sync mode that compares an archive file to a playlist and downloads or removes changed tracks.

Official sources

  1. Issues
  2. License: GPL-2.0
  3. README
  4. Releases
  5. scdl-org/scdl on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/scdl-org-scdl.svg)](https://hysenlabs.com/projects/scdl-org-scdl)