Quick Start

This guide explains the most common ways to use musicdl in both the command line and Python. It is written for practical, day-to-day usage, so the focus is on the workflows most users need first: searching songs, choosing music sources, downloading playlists, saving files to custom folders, and passing cookies or request settings when needed.

Typical Usage

(1) Run Musicdl in Interactive Mode

The quickest way to verify that musicdl is installed correctly is to start the interactive terminal UI.

from musicdl import musicdl

music_client = musicdl.MusicClient(
    music_sources=['MiguMusicClient', 'NeteaseMusicClient', 'QQMusicClient', 'KuwoMusicClient', 'QianqianMusicClient']
)
music_client.startcmdui()

Equivalent command-line usage:

musicdl -m MiguMusicClient,NeteaseMusicClient,QQMusicClient,KuwoMusicClient,QianqianMusicClient

By default, musicdl uses five Mainland China sources for search and download:

MiguMusicClient, NeteaseMusicClient, QQMusicClient, KuwoMusicClient, QianqianMusicClient

If you want overseas sources, specify them explicitly each time, for example:

musicdl -m QobuzMusicClient,JamendoMusicClient,YouTubeMusicClient

If you already know where a song is likely to be available, it is usually better to search a small number of sources:

musicdl -m NeteaseMusicClient,QQMusicClient

Interactive selection keys:

  • / : move cursor

  • Space: toggle selection

  • a: select all

  • i: invert selection

  • Enter: confirm and download

  • Esc or q: cancel selection

  • r: restart the program

  • q at the main prompt: exit

The demonstration is as follows:


(2) Search Directly from The Command Line

Use -k / --keyword when you already know the query text. This still opens the selection UI before downloading.

musicdl -k "Jay Chou"

Use a specific set of sources if needed:

musicdl -k "Jay Chou" -m NeteaseMusicClient,QQMusicClient

(3) Parse and Download A Playlist

Use -p / --playlist-url to parse a supported playlist URL and download all recognized tracks.

musicdl -p "https://music.163.com/#/playlist?id=3039971654" -m NeteaseMusicClient

In Python:

from musicdl import musicdl

music_client = musicdl.MusicClient(music_sources=['NeteaseMusicClient'])
song_infos = music_client.parseplaylist("https://music.163.com/#/playlist?id=7583298906")
music_client.download(song_infos=song_infos)

Note:

  • --keyword and --playlist-url cannot be used at the same time.

CLI Help

You can always inspect the full command-line interface with:

musicdl --help
Show CLI help output
Usage: musicdl [OPTIONS]

Options:
  --version                       Show the version and exit.
  -k, --keyword TEXT              The keywords for the music search. If left
                                  empty, an interactive terminal will open
                                  automatically.
  -p, --playlist-url, --playlist_url TEXT
                                  Given a playlist URL, e.g., "https://music.1
                                  63.com/#/playlist?id=7583298906", musicdl
                                  automatically parses the playlist and
                                  downloads all tracks in it.
  -m, --music-sources, --music_sources TEXT
                                  The music search and download sources.
                                  [default: MiguMusicClient,NeteaseMusicClient
                                  ,QQMusicClient,KuwoMusicClient,QianqianMusic
                                  Client]
  -i, --init-music-clients-cfg, --init_music_clients_cfg TEXT
                                  Config such as `work_dir` for each music
                                  client as a JSON string.
  -r, --requests-overrides, --requests_overrides TEXT
                                  Requests.get / Requests.post kwargs such as
                                  `headers` and `proxies` for each music
                                  client as a JSON string.
  -c, --clients-threadings, --clients_threadings TEXT
                                  Number of threads used for each music client
                                  as a JSON string.
  -s, --search-rules, --search_rules TEXT
                                  Search rules for each music client as a JSON
                                  string.
  --help                          Show this message and exit.

Common Configuration

(1) Save Files to Custom Folders

Python:

from musicdl import musicdl

init_music_clients_cfg = {
    'MiguMusicClient': {'work_dir': 'migu'},
    'NeteaseMusicClient': {'work_dir': 'netease'},
    'QQMusicClient': {'work_dir': 'qq'},
}

music_client = musicdl.MusicClient(
    music_sources=['MiguMusicClient', 'NeteaseMusicClient', 'QQMusicClient'],
    init_music_clients_cfg=init_music_clients_cfg,
)
music_client.startcmdui()

Command line:

musicdl -m MiguMusicClient,NeteaseMusicClient,QQMusicClient \
  -i '{"MiguMusicClient": {"work_dir": "migu"}, "NeteaseMusicClient": {"work_dir": "netease"}, "QQMusicClient": {"work_dir": "qq"}}'

(2) Pass Cookies for VIP or Logged-in Access

If a source works better when logged in, provide cookies from that platform’s web session, e.g., QQMusicClient:

from musicdl import musicdl

your_vip_cookies_with_str_or_dict_format = ""

init_music_clients_cfg = {
    'QQMusicClient': {
        'default_search_cookies': your_vip_cookies_with_str_or_dict_format,
        'default_download_cookies': your_vip_cookies_with_str_or_dict_format,
    }
}

music_client = musicdl.MusicClient(
    music_sources=['NeteaseMusicClient', 'QQMusicClient'],
    init_music_clients_cfg=init_music_clients_cfg,
)
music_client.startcmdui()

Command line:

musicdl -m NeteaseMusicClient,QQMusicClient \
  -i '{"QQMusicClient": {"default_search_cookies": "YOUR_COOKIES", "default_download_cookies": "YOUR_COOKIES"}}'

(3) Increase The Number of Search Results from One Source

from musicdl import musicdl

init_music_clients_cfg = {
    'QQMusicClient': {'search_size_per_source': 20}
}

music_client = musicdl.MusicClient(
    music_sources=['NeteaseMusicClient', 'QQMusicClient'],
    init_music_clients_cfg=init_music_clients_cfg,
)
music_client.startcmdui()

Equivalent command:

musicdl -m NeteaseMusicClient,QQMusicClient \
  -i '{"QQMusicClient": {"search_size_per_source": 20}}'

(4) Use Free Proxies Automatically

If you want to use the pyfreeproxy library to fetch free proxies automatically:

from musicdl import musicdl

init_music_clients_cfg = {
    'NeteaseMusicClient': {
        'search_size_per_source': 1000,
        'auto_set_proxies': True,
        'freeproxy_settings': {
            'proxy_sources': ["ProxyScrapeProxiedSession", "ProxylistProxiedSession"],
            'init_proxied_session_cfg': {
                'max_pages': 2,
                'filter_rule': {
                    'country_code': ["CN"],
                    'anonymity': ["elite"],
                    'protocol': ["http", "https"],
                },
            },
            'disable_print': True,
            'max_tries': 20,
        },
    }
}

music_client = musicdl.MusicClient(
    music_sources=['NeteaseMusicClient'],
    init_music_clients_cfg=init_music_clients_cfg,
)
music_client.startcmdui()

Command line:

musicdl -m NeteaseMusicClient \
  -i '{"NeteaseMusicClient": {"search_size_per_source": 1000, "auto_set_proxies": true, "freeproxy_settings": {"proxy_sources": ["ProxyScrapeProxiedSession", "ProxylistProxiedSession"], "init_proxied_session_cfg": {"max_pages": 2, "filter_rule": {"country_code": ["CN"], "anonymity": ["elite"], "protocol": ["http", "https"]}}, "disable_print": true, "max_tries": 20}}}'

(5) Override Request Settings Per Source

Use requests_overrides when you need to pass extra request options such as proxies, timeout, or verify.

from musicdl import musicdl

requests_overrides = {
    'NeteaseMusicClient': {
        'timeout': (10, 30),
        'verify': False,
        'headers': {'User-Agent': 'Mozilla/5.0'},
    }
}

music_client = musicdl.MusicClient(
    music_sources=['NeteaseMusicClient'],
    requests_overrides=requests_overrides,
)

search_results = music_client.search(keyword='tail ring')
music_client.download(song_infos=search_results)

Command line:

musicdl -k "tail ring" -m NeteaseMusicClient \
  -r '{"NeteaseMusicClient": {"timeout": [10, 30], "verify": false, "headers": {"User-Agent": "Mozilla/5.0"}}}'

(6) Pass Source-Specific Search Rules

Use search_rules when a source supports extra search options. Behavior is implementation-specific.

from musicdl import musicdl

search_rules = {
    'FiveSingMusicClient': {
        'sort': 1,
        'filter': 0,
        'type': 0,
    }
}

music_client = musicdl.MusicClient(
    music_sources=['FiveSingMusicClient'],
    search_rules=search_rules,
)
music_client.startcmdui()

Command line:

musicdl -m FiveSingMusicClient \
  -s '{"FiveSingMusicClient": {"sort": 1, "filter": 0, "type": 0}}'

(7) Adjust Thread Counts Per Source

from musicdl import musicdl

clients_threadings = {
    'NeteaseMusicClient': 8,
    'QQMusicClient': 4,
}

music_client = musicdl.MusicClient(
    music_sources=['NeteaseMusicClient', 'QQMusicClient'],
    clients_threadings=clients_threadings,
)
music_client.startcmdui()

Command line:

musicdl -m NeteaseMusicClient,QQMusicClient \
  -c '{"NeteaseMusicClient": 8, "QQMusicClient": 4}'

Separate Search and Download

You can call .search() and .download() separately to inspect intermediate results or build custom workflows.

from musicdl import musicdl

music_client = musicdl.MusicClient(music_sources=['NeteaseMusicClient'])

search_results = music_client.search(keyword='尾戒')
print(search_results)

song_infos = []
for song_infos_per_source in search_results.values():
    song_infos.extend(song_infos_per_source)

music_client.download(song_infos=song_infos)

Secondary Development

You can also bypass the unified MusicClient and use a specific client directly. For example:

from musicdl.modules.sources import NeteaseMusicClient

netease_music_client = NeteaseMusicClient()

search_results = netease_music_client.search(keyword='那些年')
print(search_results)

netease_music_client.download(song_infos=search_results)

To inspect all registered client classes:

from musicdl.modules import MusicClientBuilder

print(MusicClientBuilder.REGISTERED_MODULES)

Download Playlist Items

From musicdl v2.9.0 onward, support for playlist parsing and downloading is being added gradually, now including,

AppleMusicClient,      DeezerMusicClient,       FiveSingMusicClient,    JamendoMusicClient,      JooxMusicClient,
KuwoMusicClient,       KugouMusicClient,        MiguMusicClient,        NeteaseMusicClient,      QQMusicClient,
QianqianMusicClient,   QobuzMusicClient,        SoundCloudMusicClient,  StreetVoiceMusicClient,  SodaMusicClient,
SpotifyMusicClient,    TIDALMusicClient,        FMAMusicClient,         JioSaavnMusicClient,     BodianMusicClient,
SunoMusicClient,       MOOVMusicClient,

You can download a supported playlist directly from the terminal:

# Parse and Download Apple Music Playlist
# >>> not use wrapper
musicdl -p "https://music.apple.com/cn/playlist/%E5%8D%81%E5%A4%A7%E4%B8%93%E8%BE%91/pl.u-mJy81mECzBL49zM" -m AppleMusicClient -i "{'AppleMusicClient': {'default_parse_cookies': your_vip_cookies_with_str_or_dict_format}}"
# >>> use wrapper
musicdl -p "https://music.apple.com/cn/playlist/%E5%8D%81%E5%A4%A7%E4%B8%93%E8%BE%91/pl.u-mJy81mECzBL49zM" -m AppleMusicClient -i "{'AppleMusicClient': {'use_wrapper': True, 'wrapper_account_url': 'http://127.0.0.1:30020/', 'wrapper_decrypt_ip': '127.0.0.1:10020'}}"
# Parse and Download Bodian Music Playlist
musicdl -p "https://h5app.kuwo.cn/m/bodian/collection.html?uid=1798690&playlistId=1669719&source=5&ownerId=1798690"
# Parse and Download Deezer Music Playlist
musicdl -p "https://www.deezer.com/us/playlist/4697225044" -m DeezerMusicClient
# Parse and Download 5SING Music Playlist
musicdl -p "https://5sing.kugou.com/yeluoluo/dj/631b3fa72418b11003089b8d.html" -m FiveSingMusicClient
# Parse and Download FMA Music Playlist
musicdl -p "https://freemusicarchive.org/member/Creative_Commons/cc-20th-anniversary-open-mix" -m FMAMusicClient -i "{'FMAMusicClient': {'default_parse_cookies': your_vip_cookies_with_str_or_dict_format}}"
# Parse and Download Jamendo Music Playlist
musicdl -p "https://www.jamendo.com/playlist/500544876/best-of-february-2020" -m JamendoMusicClient
# Parse and Download Joox Music Playlist
musicdl -p "https://www.joox.com/hk/playlist/MqgK_LYD3Sb3I9Iziq+8NA==" -m JooxMusicClient
# Parse and Download JioSaavn Music Playlist
musicdl -p "https://www.jiosaavn.com/featured/world-music-day-telugu/3sLj61YBHdI_" -m JioSaavnMusicClient
# Parse and Download Kuwo Music Playlist
musicdl -p "https://www.kuwo.cn/playlist_detail/2358858706" -m KuwoMusicClient
# Parse and Download Kugou Music Playlist
musicdl -p "https://www.kugou.com/yy/special/single/3280341.html" -m KugouMusicClient
# Parse and Download Migu Music Playlist
musicdl -p "https://music.migu.cn/v5/#/playlist?playlistId=228114498&playlistType=ordinary" -m MiguMusicClient
# Parse and Download MOOV Music Playlist
musicdl -p "https://moov.hk/?utm_source=ios&utm_medium=copylink&utm_campaign=sharing_UPL-6742190#/playlist/PP1000000965" -m MOOVMusicClient -i "{'MOOVMusicClient': {'default_parse_cookies': your_vip_cookies_with_str_or_dict_format}}"
# Parse and Download NetEase Music Playlist
musicdl -p "https://music.163.com/#/playlist?id=3039971654" -m NeteaseMusicClient
# Parse and Download QQ Music Playlist
musicdl -p "https://y.qq.com/n/ryqq_v2/playlist/8740590963" -m QQMusicClient
# Parse and Download QianQian Music Playlist
musicdl -p "https://music.91q.com/songlist/295893" -m QianqianMusicClient
# Parse and Download Qobuz Music Playlist
musicdl -p "https://open.qobuz.com/playlist/22318381" -m QobuzMusicClient
# Parse and Download StreetVoice Music Playlist
musicdl -p "https://www.streetvoice.cn/morgan22/playlists/436444/" -m StreetVoiceMusicClient
# Parse and Download SoundCloud Music Playlist
musicdl -p "https://soundcloud.com/pandadub/sets/the-lost-ship" -m SoundCloudMusicClient
# Parse and Download Soda Music Playlist
musicdl -p "https://qishui.douyin.com/s/iHFSgNKw/" -m SodaMusicClient
# Parse and Download Spotify Music Playlist
musicdl -p "https://open.spotify.com/playlist/37i9dQZF1E8NWHOpySOxQd" -m SpotifyMusicClient
# Parse and Download Suno Music Playlist
musicdl -p "https://suno.com/playlist/71f56f55-93a8-4c93-830d-6762853cc862" -m SunoMusicClient
# Parse and Download TIDAL Music Playlist
musicdl -p "https://tidal.com/playlist/a94e7dce-da66-413d-81a5-990328afa3c9" -m TIDALMusicClient -i "{'TIDALMusicClient': {'default_parse_cookies': your_vip_cookies_with_str_or_dict_format}}"

Alternatively, in Python:

from musicdl import musicdl

init_music_clients_cfg = {
    'NeteaseMusicClient': {'default_parse_cookies': YOUR_VIP_COOKIES}
}

music_client = musicdl.MusicClient(
    music_sources=['NeteaseMusicClient'],
    init_music_clients_cfg=init_music_clients_cfg,
)

song_infos = music_client.parseplaylist("https://music.163.com/#/playlist?id=7583298906")
music_client.download(song_infos=song_infos)

WhisperLRC

On some music platforms, it is not possible to obtain lyric files directly, for example XimalayaMusicClient, LizhiMusicClient, LRTSMusicClient, QingtingMusicClient and MituMusicClient. To handle this, musicdl provides a faster-whisper-based interface that can generate lyrics automatically.

Generate lyrics from a local file:

from musicdl.modules import WhisperLRC

your_local_music_file_path = 'xxx.flac'
print(WhisperLRC(model_size_or_path='base').fromfilepath(your_local_music_file_path))

Available model_size_or_path values:

tiny, tiny.en, base, base.en, small, small.en, distil-small.en, medium, medium.en, distil-medium.en, large-v1, large-v2, large-v3, large, distil-large-v2, distil-large-v3, large-v3-turbo, turbo

In general, larger models generate better lyrics but take longer to run.

Use the environment variable ENABLE_WHISPERLRC=True to toggle on-the-fly lyric generation for all music downloads. For example:

export ENABLE_WHISPERLRC=True

This is usually not recommended for normal downloading workflows, because it can make one run take a very long time unless you keep search_size_per_source=1 and use a very small Whisper model such as tiny.

You can also generate lyrics from a direct audio URL:

from musicdl.modules import WhisperLRC

music_link = ''
print(WhisperLRC(model_size_or_path='base').fromurl(music_link))

Scenarios Where Quark Netdisk Login Cookies Are Required

Some websites share high-quality or lossless music through Quark Netdisk links, for example:

MituMusicClient, GequbaoMusicClient, YinyuedaoMusicClient, BuguyyMusicClient

If you want to download high-quality or lossless files from these sources, provide the cookies from your logged-in Quark Netdisk web session.

from musicdl import musicdl

init_music_clients_cfg = {
    'YinyuedaoMusicClient': {'quark_parser_config': {'cookies': your_cookies_with_str_or_dict_format}},
    'GequbaoMusicClient': {'quark_parser_config': {'cookies': your_cookies_with_str_or_dict_format}},
    'MituMusicClient': {'quark_parser_config': {'cookies': your_cookies_with_str_or_dict_format}},
    'BuguyyMusicClient': {'quark_parser_config': {'cookies': your_cookies_with_str_or_dict_format}},
}

music_client = musicdl.MusicClient(
    music_sources=['MituMusicClient', 'YinyuedaoMusicClient', 'GequbaoMusicClient', 'BuguyyMusicClient'],
    init_music_clients_cfg=init_music_clients_cfg,
)
music_client.startcmdui()

Please note:

  • musicdl does not provide any speed-limit bypass for Quark Netdisk.

  • If the cookies belong to a non-VIP Quark account, the download speed may be only a few hundred KB/s.

  • Quark may first save the file into your own account before downloading it.

  • If your Quark storage is insufficient, the download may fail.

Common Issues and Solutions (FAQ)

How to Parse New Kugou Web Playlist URLs?

If you have a new playlist link, for example, https://www.kugou.com/songlist/gcid_3zs9qlpmzdz003/, you need to manually extract the special ID via your browser.

  1. Open the playlist link in your browser and make sure you are logged into Kugou Music.

  2. Open Developer Tools (F12) and inspect the returned HTML page in the Network panel.

  3. Search for the keyword "specialid".

  4. The number immediately after it is the special ID.

  5. Construct a new URL in the form: https://www.kugou.com/yy/special/single/{YOUR_SPECIAL_ID}.html

  6. Use that new URL as the playlist input for musicdl.

Why is The Downloaded Apple Music Playlist Incomplete?

musicdl currently only supports parsing Apple Music playlists with a maximum of 300 tracks.

If your playlist exceeds this limit, split it into several smaller playlists and download them separately.