# 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.
```python
from musicdl import musicdl
music_client = musicdl.MusicClient(
music_sources=['MiguMusicClient', 'NeteaseMusicClient', 'QQMusicClient', 'KuwoMusicClient', 'QianqianMusicClient']
)
music_client.startcmdui()
```
Equivalent command-line usage:
```bash
musicdl -m MiguMusicClient,NeteaseMusicClient,QQMusicClient,KuwoMusicClient,QianqianMusicClient
```
By default, musicdl uses five Mainland China sources for search and download:
```python
MiguMusicClient, NeteaseMusicClient, QQMusicClient, KuwoMusicClient, QianqianMusicClient
```
If you want overseas sources, specify them explicitly each time, for example:
```bash
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:
```bash
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.
```bash
musicdl -k "Jay Chou"
```
Use a specific set of sources if needed:
```bash
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.
```bash
musicdl -p "https://music.163.com/#/playlist?id=3039971654" -m NeteaseMusicClient
```
In Python:
```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:
```bash
musicdl --help
```
Show CLI help output
```bash
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:
```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:
```bash
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`:
```python
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:
```bash
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
```python
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:
```bash
musicdl -m NeteaseMusicClient,QQMusicClient \
-i '{"QQMusicClient": {"search_size_per_source": 20}}'
```
(4) Use Free Proxies Automatically
If you want to use the [pyfreeproxy](https://github.com/CharlesPikachu/freeproxy) library to fetch free proxies automatically:
```python
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:
```bash
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`.
```python
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:
```bash
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.
```python
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:
```bash
musicdl -m FiveSingMusicClient \
-s '{"FiveSingMusicClient": {"sort": 1, "filter": 0, "type": 0}}'
```
(7) Adjust Thread Counts Per Source
```python
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:
```bash
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.
```python
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:
```python
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:
```python
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,
```python
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:
```sh
# 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:
```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:
```python
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:
```python
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:
```bash
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:
```python
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](https://pan.quark.cn/) links, for example:
```python
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.
```python
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.