YoutubeDL-Server
Web and REST interface to Youtube-DL for downloading videos onto a server.
Web and REST interface to Youtube-DL for downloading videos onto a server.


[](https://raw.githubusercontent.com/nbr23/youtube-dl-server/master/LICENSE)
# youtube-dl-server
Simple Web and REST interface for downloading youtube videos onto a server.
[`starlette`](https://www.starlette.io/) +
[yt-dlp](https://github.com/yt-dlp/yt-dlp) / [`youtube-dl`](https://github.com/rg3/youtube-dl)
Forked from [manbearwiz/youtube-dl-server](https://github.com/manbearwiz/youtube-dl-server).
![screenshot][1]
![screenshot][2]
## Running
For easier deployment, a docker image is available on
[dockerhub](https://hub.docker.com/r/nbr23/youtube-dl-server):
- `nbr23/youtube-dl-server:yt-dlp` or simply `nbr23/youtube-dl-server` to use `yt-dlp`
- `nbr23/youtube-dl-server:youtube-dl` to use `youtube-dl`. Note that the latest release of `youtube-dl` is pretty [outdated](https://github.com/ytdl-org/youtube-dl/releases/tag/2021.12.17).
### Docker CLI
This example uses the docker run command to create the container to run the
app. Note the `-v` argument to specify the volume and its binding on the host.
This directory will be used to output the resulting videos.
```shell
docker run -d --name youtube-dl -p 8080:8080 -v $HOME/youtube-dl:/youtube-dl nbr23/youtube-dl-server:latest
```
OR for yt-dlp:
```shell
docker run -d --name youtube-dl -p 8080:8080 -v $HOME/youtube-dl:/youtube-dl nbr23/youtube-dl-server:yt-dlp
```
### Docker Compose
This is an example service definition that could be put in `docker-compose.yml`.
```yml
youtube-dl:
image: "nbr23/youtube-dl-server:latest"
volumes:
- $HOME/youtube-dl:/youtube-dl
- ./config.yml:/app_config/config.yml:ro # Overwrite the container's config file with your own configuration
ports:
- 8080:8080
restart: always
```
## Configuration
Configuration is done through the config.yml file at the root of the project.
An alternate configuration path or file path can be forced by setting the environment
variable `YDL_CONFIG_PATH`:
```shell
export YDL_CONFIG_PATH=/var/local/youtube-dl-server/config.yml
```
In the above case, if `/var/local/youtube-dl-server/config.yml` does not exist, it will be created with the default options.
```shell
export YDL_CONFIG_PATH=/var/local/youtube-dl-server/
```
In the above case, if `/var/local/youtube-dl-server/config.yml` does not exist, it will be created with the default options as well.
### ydl_server options
| Key | Default | Description |
|-----|---------|-------------|
| `port` | `8080` | Port to listen on |
| `host` | `0.0.0.0` | IP to bind to |
| `metadata_db_path` | `/youtube-dl/.ydl-metadata.db` | Path to the SQLite job database |
| `output_playlist` | `/youtube-dl/%(playlist_title)s [%(playlist_id)s]/%(title)s.%(ext)s` | Output template for playlists and multi-URL jobs |
| `max_log_entries` | `100` | Maximum number of job history entries to keep |
| `default_format` | `video/best` | Default format pre-selected in the UI |
| `download_workers_count` | `2` | Number of parallel download worker threads |
| `forwarded_allow_ips` | `None` | Comma-separated list of IPs to trust proxy headers from (passed to uvicorn) |
| `proxy_headers` | `True` | Trust `X-Forwarded-Proto`, `X-Forwarded-For`, `X-Forwarded-Port` headers (passed to uvicorn) |
| `debug` | `False` | Enable debug mode |
Minimum required configuration:
```yaml
ydl_server:
port: 8080
host: 0.0.0.0
metadata_db_path: '/youtube-dl/.ydl-metadata.db'
ydl_options:
output: '/youtube-dl/%(title)s [%(id)s].%(ext)s'
cache-dir: '/youtube-dl/.cache'
```
### ydl_options
Additional yt-dlp/youtube-dl parameters can be set in the `ydl_options` section. Add
parameters by removing the leading `--` from the flag name.
For example, to write subtitles in spanish, the yt-dlp command would be:
`yt-dlp --write-sub --sub-lang es URL`
Which translates to:
```yaml
ydl_options:
output: '/youtube-dl/%(title)s [%(id)s].%(ext)s'
cache-dir: '/youtube-dl/.cache'
write-sub: True
sub-lang: es
```
### Profiles
Profiles are named configuration sets selectable in the UI. Each profile can
override any `ydl_options`.
```yaml
profiles:
podcast:
name: 'Audio Podcasts'
ydl_options:
output: '/youtube-dl/Podcast/%(title)s [%(id)s].%(ext)s'
format: bestaudio/best
write-thumbnail: True
embed-thumbnail: True
add-metadata: True
audio-quality: 0
extract-audio: True
audio-format: mp3
philosophy_lectures:
name: 'Philosophy Lectures'
ydl_options:
output: '/youtube-dl/Lectures/Philosophy/%(title)s [%(id)s].%(ext)s'
write-thumbnail: True
embed-thumbnail: True
add-metadata: True
verbose: True
```
![screenshot][3]
## Python
Requires Python ^3.8.
Install dependencies:
```shell
pip install -r requirements.txt
```
Build the frontend:
```shell
cd front && npm install && npm run build
```
Run the server:
```shell
python3 -u ./youtube-dl-server.py
```
To force a specific yt-dlp/youtube-dl fork, set the `YOUTUBE_DL` environment variable:
```shell
YOUTUBE_DL=yt-dlp python3 -u ./youtube-dl-server.py
```
The following environment variables are used for version display in the UI:
| Variable | Description |
|----------|-------------|
| `YOUTUBE_DL` | The yt-dlp/youtube-dl module to use (`yt-dlp`, `youtube-dl`) |
| `YDLS_VERSION` | Version string shown in the server info endpoint |
| `YDLS_RELEASE_DATE` | Release date string shown in the server info endpoint |
## Usage
### Web UI
Navigate to `http://{{host}}:8080/` and enter the URL to download.
### REST API
#### Queue a download
```shell
curl -X POST \
-H 'Content-Type: application/json' \
--data-raw '{"url": "{{URL}}", "format": "video/best"}' \
http://{{host}}:8080/api/downloads
```
Accepted body fields:
| Field | Type | Description |
|-------|------|-------------|
| `url` | string | Single URL to download |
| `urls` | array | Multiple URLs to download as one job |
| `format` | string | Format string (see formats below) |
| `profile` | string | Profile name from config |
| `audio_format` | string | Audio format (e.g. `mp3`, `aac`) |
| `force_generic_extractor` | bool | Force use of the generic extractor |
| `extra_params` | object | Extra parameters; `title` key overrides the output filename |
Available format values:
| Value | Description |
|-------|-------------|
| `video/best` | Best video+audio (default) |
| `video/bestvideo` | Best video quality |
| `video/mp4` | MP4 |
| `video/webm` | WebM |
| `video/mkv` | Matroska |
| `video/avi` | AVI |
| `video/flv` | Flash Video |
| `video/ogg` | Ogg |
| `bestaudio/best` | Best audio |
| `audio/mp3` | MP3 |
| `audio/aac` | AAC |
| `audio/flac` | FLAC |
| `audio/m4a` | M4A |
| `audio/opus` | Opus |
| `audio/vorbis` | Vorbis |
| `audio/wav` | WAV |
#### List jobs
```shell
curl http://{{host}}:8080/api/downloads
```
Query parameters:
| Parameter | Description |
|-----------|-------------|
| `status` | Filter by status: `Running`, `Completed`, `Failed`, `Pending`, `Aborted` |
| `show_logs` | Include log output in response, `1` (default) or `0` |
#### Queue statistics
```shell
curl http://{{host}}:8080/api/downloads/stats
```
#### Clean old job entries
Removes completed and failed entries beyond `max_log_entries`:
```shell
curl -X POST http://{{host}}:8080/api/downloads/clean
```
#### Purge all job history
```shell
curl -X DELETE http://{{host}}:8080/api/downloads
```
#### Fetch metadata without downloading
```shell
curl -X POST \
-H 'Content-Type: application/json' \
--data-raw '{"url": "{{URL}}"}' \
http://{{host}}:8080/api/metadata
```
#### Stop a job
```shell
curl -X POST http://{{host}}:8080/api/jobs/{{job_id}}/stop
```
#### Retry a job
```shell
curl -X POST http://{{host}}:8080/api/jobs/{{job_id}}/retry
```
#### Delete a job entry
```shell
curl -X DELETE http://{{host}}:8080/api/jobs/{{job_id}}
```
#### List downloaded files
```shell
curl http://{{host}}:8080/api/finished
```
#### Delete a downloaded file
```shell
curl -X DELETE http://{{host}}:8080/api/finished/{{filename}}
```
#### Server info
```shell
curl http://{{host}}:8080/api/info
```
#### Available formats
```shell
curl http://{{host}}:8080/api/formats
```
#### Supported extractors
```shell
curl http://{{host}}:8080/api/extractors
```
### Bookmarklet
Add the following bookmarklet to your bookmark bar to send the current page URL
to your youtube-dl-server instance.
#### HTTPS
If your youtube-dl-server is served through HTTPS (behind a reverse proxy
handling HTTPS for example), you can use the following bookmarklet:
```javascript
javascript:fetch("https://${host}/api/downloads",{body:JSON.stringify({url:window.location.href,format:"video/best"}),method:"POST",headers:{'Content-Type':'application/json'}});
```
#### Plain HTTP
If you are hosting it without HTTPS, the previous bookmarklet will likely be
blocked by your browser (mixed content when used on HTTPS sites).
Instead, you can use the following bookmarklet:
```javascript
javascript:(function(){document.body.innerHTML += '<form name="ydl_form" method="POST" action="http://${host}/api/downloads"><input name="url" type="url" value="'+window.location.href+'"/></form>';document.ydl_form.submit()})();
```
## Notes
### Extra format support
`ffmpeg` is required for format conversion and audio extraction in some
scenarios.
## Additional references
* [ansible-role-youtubedl-server](https://github.com/nbr23/ansible-role-youtubedl-server)
* [ytdl-k8s](https://github.com/droopy4096/ytdl-k8s) - `youtube-dl-server` Helm chart (uses `youtube-dl-server` image for kubernetes deployment)
* [starlette](https://www.starlette.io/)
* [youtube-dl](https://github.com/rg3/youtube-dl)
* [yt-dlp](https://github.com/yt-dlp/yt-dlp)
[1]:youtube-dl-server.png
[2]:youtube-dl-server-logs.png
[3]:youtube-dl-server-profiles.png
Manage requests for your media library, supports Plex, Jellyfin and Emby media servers (fork of Overseerr).
Music discovery tool that provides recommendations based on selected Lidarr artists, using Spotify or LastFM.
Manage requests for your media library. It integrates with your existing services, such as Sonarr, Radarr, and Plex!.