Certain configuration values can be set via environment variables, using the -e parameter on the docker command line,
or the environment: section in compose.yaml file.
The compose.yaml file provides the standard container configuration. Use the reference below for
additional application settings.
Note
Most environment variables are shared between native and container deployments, but some default values differ for native builds. See Native builds for the native-specific defaults.
Click to expand all environment variables
| Environment Variable | Description | Default |
|---|---|---|
| TZ | The timezone to use for the application | (not_set) |
| YTP_OUTPUT_TEMPLATE | The template for the filenames of the downloaded videos | %(title)s.%(ext)s |
| YTP_FILENAME_TRIM | Remove overlong filename content from start, middle, or end |
(empty) |
| YTP_FILENAME_TRIM_REGEXES | JSON array of regexes matching filename content that must be kept | [] |
| YTP_DEFAULT_PRESET | The default preset to use for the download | default |
| YTP_INSTANCE_TITLE | The title of the instance | (not_set) |
| YTP_FILE_LOGGING | Whether to log to file | true |
| YTP_DOWNLOAD_PATH | Path to where the downloads will be saved | /downloads |
| YTP_MAX_WORKERS | The maximum number of workers to use for downloading | 20 |
| YTP_MAX_WORKERS_PER_EXTRACTOR | The maximum number of concurrent downloads per extractor | 2 |
| YTP_MONITOR_ENABLED | Enable app resource monitoring | false |
| YTP_MONITOR_INTERVAL | Sampling interval in seconds for resource monitoring | 30 |
| YTP_MONITOR_RETENTION_HOURS | How many hours to retain raw monitor samples in the stats database | 24 |
| YTP_DISABLE_AUTH | Disable application authentication | false |
| YTP_AUTH_SESSION_DAYS | Number of days before browser sessions expire (minimum 1) |
30 |
| YTP_CORS_ORIGINS | Comma-separated exact origins, or * for non-cookie clients |
* |
| YTP_TRUSTED_PROXIES | Comma-separated proxy IP addresses and/or CIDRs trusted for XFF | (empty) |
| YTP_CONSOLE_ENABLED | Whether to enable the console | false |
| YTP_REMOVE_FILES | Remove the actual file when clicking the remove button | false |
| YTP_CONFIG_PATH | Path to where the config files will be stored. | /config |
| YTP_TEMP_PATH | Path to where tmp files are stored. | /tmp |
| YTP_TEMP_KEEP | Whether to keep the Individual video temp directory or remove it | false |
| YTP_HOST | Which IP address to bind to | 0.0.0.0 |
| YTP_PORT | Which port to bind to | 8081 |
| YTP_LOG_LEVEL | Log level | info |
| YTP_STREAMER_VCODEC | The video encoding codec, default to GPU and fallback to software | "" |
| YTP_STREAMER_ACODEC | The audio codec to use for in-browser streaming | aac |
| YTP_VAAPI_DEVICE | The VAAPI device to use for hardware acceleration. | /dev/dri/renderD128 |
| YTP_ACCESS_LOG | Whether to log access to the web server | true |
| YTP_DEBUG | Whether to turn on debug mode | false |
| YTP_DEBUGPY_PORT | The port to use for the debugpy debugger | 5678 |
| YTP_EXTRACT_INFO_TIMEOUT | The timeout for extracting video information | 70 |
| YTP_EXTRACT_INFO_KEEP_ALIVE | Keep extract info worker processes alive between requests | false |
| YTP_PIP_PACKAGES | A space separated list of pip packages to install | (not_set) |
| YTP_PIP_IGNORE_UPDATES | Do not update the custom pip packages | false |
| YTP_PYTHON_PATH | Extra python library directory | (not_set) |
| YTP_PICTURES_BACKENDS | A comma separated list of picture URLs to use | (default) |
| YTP_BROWSER_CONTROL_ENABLED | Whether to enable the file browser actions | false |
| YTP_BGUTIL_ENABLED | Whether to run the bundled PO-token provider | true |
| YTP_YTDLP_AUTO_UPDATE | Whether to enable the auto update for yt-dlp | true |
| YTP_YTDLP_DEBUG | Whether to turn debug logging for the internal yt-dlp package |
false |
| YTP_YTDLP_VERSION | The version of yt-dlp to use. Defaults to latest version | (not_set) |
| YTP_BROWSER_URL | Remote browser endpoint for the browser extractor | (not_set) |
| YTP_FLARESOLVERR_URL | FlareSolverr or Trawl endpoint URL. | (not_set) |
| YTP_FLARESOLVERR_MAX_TIMEOUT | Max FlareSolverr/Trawl challenge timeout in seconds | 120 |
| YTP_FLARESOLVERR_CLIENT_TIMEOUT | HTTP client timeout (seconds) when calling FlareSolverr/Trawl | 120 |
| YTP_FLARESOLVERR_CACHE_TTL | The cache TTL (in seconds) for FlareSolverr/Trawl solutions | 600 |
| YTP_BASE_PATH | Set this if you are serving YTPTube from sub-folder | / |
| YTP_PREVENT_LIVE_PREMIERE | Prevents the initial YouTube premiere stream from being downloaded | true |
| YTP_QUEUE_DISPLAY_LIMIT | Max queued downloads returned to the UI. 0 = unlimited |
100 |
| YTP_LIVE_PREMIERE_BUFFER | buffer time in minutes to add to video duration | 5 |
| YTP_TASKS_HANDLER_TIMER | The cron expression for the tasks handler timer | 15 */1 * * * |
| YTP_TEMP_DISABLED | Disable temp files handling. | false |
| YTP_RETRY | Number of additional attempts for retryable download failures. | 0 |
| YTP_RETRY_FRESH | Use a fresh download on the final retry attempt. | false |
| YTP_SIMPLE_MODE | Switch default interface to Simple mode. | false |
| YTP_STATIC_UI_PATH | Path to custom static UI files. | (not_set) |
| YTP_AUTO_CLEAR_HISTORY_DAYS | Number of days after which completed download history is cleared. | 0 |
| YTP_DEFAULT_PAGINATION | The default number of items per page for history. | 50 |
| YTP_TASK_HANDLER_RANDOM_DELAY | The maximum random delay in seconds before starting a task handler. | 60 |
| YTP_IGNORE_ARCHIVED_ITEMS | Don't report archived items in the download history. | false |
| YTP_CHECK_FOR_UPDATES | Whether to check for application updates. | true |
| YTP_EXTRACT_INFO_CONCURRENCY | The number of concurrent extract info operations. | 4 |
| YTP_THUMB_CONCURRENCY | The number of concurrent ffmpeg thumbnail generations allowed. | 2 |
| YTP_THUMB_GENERATE | Enable ffmpeg thumbnail generation when no local thumbnail exists. | true |
| YTP_THUMB_SIDECAR | Save generated thumbnails next to media instead of temp cache. | false |
[!NOTE] To raise the worker limit for a specific extractor, set an env variable using this format:
YTP_MAX_WORKERS_FOR_<EXTRACTOR_NAME>The extractor name must be uppercase. You can find the extractor name in the download logs. This value cannot be higher thanYTP_MAX_WORKERS; higher values are ignored.
YTP_SIMPLE_MODE=trueonly applies when the browser has no saved layout choice yet. Users can still choose a layout in WebUI Settings./?simple=1forces and saves Simple for that browser.
YTP_AUTO_CLEAR_HISTORY_DAYS0days means no automatic clearing of the download history. lowest value that will trigger the clearing is1day. This setting will NOT delete the downloaded files, it will only clear the history from the database.
YTP_EXTRACT_INFO_KEEP_ALIVE=truekeeps yt-dlp metadata extraction worker processes alive between requests. This can make playlist extraction faster, but uses more idle memory. Leave itfalseto reduce idle resource usage.
Set YTP_FILENAME_TRIM to choose which part of an overlong filename can be removed:
endtrims unprotected content from the end.starttrims unprotected content from the beginning.middletrims unprotected content from the center.- An empty value disables trimming (default).
Set YTP_FILENAME_TRIM_REGEXES to a JSON array of regular expressions. Every matched part of the filename is retained.
For example, this protects leading digits and every non-nested bracketed section:
YTP_FILENAME_TRIM: end
YTP_FILENAME_TRIM_REGEXES: '["^\\d+", "\\[[^][]*\\]"]'With these settings, an overlong filename such as:
260812 very long title that continues for hundreds of characters [youtube-random-id].mkv
can be shortened to:
260812 very long title that cont [youtube-random-id].mkv
javascript:(() => { const url = "https://ytp.example.org"; const preset = "default"; const apiKey = "ytp_..."; const mUrl = new URL(url);mUrl.pathname="/api/history/add";mUrl.searchParams.set("url",document.location.href);mUrl.searchParams.set("preset",preset);fetch(mUrl,{method: "GET",headers:{Authorization:`Bearer ${apiKey}`}}).then(j => j.json()).then(json =>alert(json.message)).catch(err =>alert(err)); })()Set url, preset, and apiKey for your YTPTube instance. Create the API key from the account menu.
Note
The bookmarklet should be served from https page, otherwise, some browsers will block the request. for mixed content.
- For Firefox via Firefox Store
- For Chrome/Chromium Browsers via Chrome Store
You can download Add To YTPTube shortcut and use it to send links to your YTPTube instance. You have to edit the shortcut and replace the following:
https://ytp.example.orgwith your YTPTube instance.- The shortcut currently uses Basic authentication. Replace its credential value with
username:ytp_...: your account username and an API key, not your account password. Leave it empty when authentication is disabled.
This shortcut lets you select a preset from your instance. You can add presets for websites that need cookies and use those presets to download directly from your iOS device.
This shortcut YTPTube To Media parses the yt-dlp
output and attempts to download media directly to your iOS device. It doesn't always work. We provide no support for
this use case beyond the shortcut itself. The shortcut doesn't parse http_headers; it parses only cookies.
Server installations require a local account by default. Open the account menu, select Create key, enter a name, and copy the key when it appears. The key is shown once.
Send API keys in the Authorization: Bearer ytp_... header.
The ?apikey=ytp_... query parameter is available for clients that cannot set headers, but URLs can appear in browser
history and proxy logs.
Use YTP_DISABLE_AUTH=true only when a trusted reverse proxy controls access. YTP_CORS_ORIGINS accepts a
comma-separated origin allowlist. Set it to * for clients that send an API key without cookies.
When YTPTube is behind a reverse proxy, session details use the transport peer address by default. To record the
actual client address from X-Forwarded-For, set YTP_TRUSTED_PROXIES to the proxy's exact IP address or CIDR (for
example, 10.0.0.10,10.0.0.0/24).
You need shell access to the machine running YTPTube. Replace USERNAME with the account username.
Assuming your YTPTube container is called ytptube, run:
docker exec -ti -w /app ytptube python -m app.scripts.reset_password --username USERNAMEFor Podman, replace docker with podman in the command above.
A successful password reset invalidates the related user's sessions.
Do not expose YTPTube to an untrusted network without authentication.
- Download arbitrary content through your IP and server.
- Delete or modify your downloaded files and database.
- Run arbitrary
yt-dlpoptions, including--exec, which executes shell commands inside the container.
The cli options field passes options to yt-dlp. Options such as --exec can run commands on the host or
inside the container.
If you expose YTPTube to untrusted networks, do one of the following:
- Enable authentication.
- Put it behind a reverse proxy with its own authentication layer (see Run behind reverse proxy).
- Keep it on a private network with no public exposure.
If you are receiving errors like:
- "OSError: [Errno 5] I/O error"
- "OSError: [Errno 18] Cross-device link: '/tmp/random_id/name.webm' -> '/downloads/name.webm'
- "Operation not permitted: '/downloads/name.webm'
This indicates an error with the container mounts. Use the paths in the root compose.yaml, then create
the necessary directories and start the stack:
mkdir -p ./config && mkdir -p ./downloads/{tmp,files} && docker compose up -dReference: Issue #363
You can do it in 3 different ways:
-
use the
--no-playlistoption in theCLI optionsfield in the download form. -
create custom field using type bool and set the field as
--no-playlistor use the following import string
import as custom field
eyJuYW1lIjoiTm8gcGxheWxpc3QiLCJkZXNjcmlwdGlvbiI6ImRvIG5vdCBwcm9jZXNzIHBsYXlsaXN0IiwiZmllbGQiOiItLW5vLXBsYXlsaXN0Iiwia2luZCI6ImJvb2wiLCJpY29uIjoiaS1sdWNpZGUtbGlzdC12aWRlbyIsIm9yZGVyIjoxLCJleHRyYXMiOnt9LCJfdHlwZSI6ImRsX2ZpZWxkIiwiX3ZlcnNpb24iOiIxLjAifQ
- Create a preset, and in the
CLI optionsfield set--no-playlist. Then select the preset, or use the following import string:
import as preset
eyJuYW1lIjoibm9fcGxheWxpc3QiLCJjbGkiOiItLW5vLXBsYXlsaXN0IiwiX3R5cGUiOiJwcmVzZXQiLCJfdmVyc2lvbiI6IjIuNiJ9
You can force specific version of yt-dlp by setting the YTP_YTDLP_VERSION environment variable for example
YTP_YTDLP_VERSION=2025.07.21 or master or nightlyThen restart the container to apply the changes.
YTPTube supports custom ytp_* placeholders in yt-dlp output template via the following syntax %(ytp_*:<args>)s.
ytp_random: random mixed letters and digits,NA number is required to specify the length of the random string, for example%(ytp_random:8)swill generate a random string of 8 characters.- if the args followed by
:sit will generate random letters only, if followed by:dit will generate random digits only.
- Template:
%(title)s [%(ytp_random:8)s].%(ext)s- Example result:
My Video [A7k2Pq9Z].mp4
- Example result:
- Template:
%(uploader)s/%(ytp_random:6:d)s - %(title)s.%(ext)s- Example result:
MyChannel/483920 - My Video.mp4
- Example result:
- Template:
%(playlist)s/%(ytp_random:10:s)s/%(title)s.%(ext)s- Example result:
Favorites/QwErTyUiOp/My Video.mp4
- Example result:
Note
%(ytp_ placeholders are a YTPTube extension and not available via console or directly via yt-dlp.
See Generic Task Definitions for complete documentation on how to create a generic task definition for sites.
The container includes the bgutil-ytdlp-pot-provider server and extractor. They are enabled by default, and yt-dlp finds the server automatically. No Preset options or additional container are required.
Set YTP_BGUTIL_ENABLED=false on the YTPTube container to disable the bundled server. Then to use the external POT
server create a Preset and add this to its CLI options field:
--extractor-args "youtubepot-bgutilhttp:base_url=http://[YOUR_BGUTIL_PROVIDER_IP]:4416"replace [YOUR_BGUTIL_PROVIDER_IP] with the IP address of the server running the POT provider. The server must be
reachable from the YTPTube container.
See the bgutil-ytdlp-pot-provider project.
Before asking a question or submitting an issue for YTPTube, please remember that YTPTube is only a wrapper for
yt-dlp. Any issues you might be experiencing with authentication to video websites,
postprocessing, permissions, other yt-dlp options configurations which seem not to work, or anything else that
concerns the workings of the underlying yt-dlp library, need not be opened on the YTPTube project.
To debug these problems, first run the yt-dlp binary directly, bypassing the UI. Once the command works, import its
options into a new preset.
If you have enabled the web terminal with the YTP_CONSOLE_ENABLED environment variable, go to Other > Terminal and
run the yt-dlp command. You can also open the download form, click advanced options, and then click the
yellow terminal icon, Run directly in console.
Assuming your YTPTube container is called ytptube, run the following on your docker host to get a shell inside the container:
docker exec -ti ytptube bash
cd /downloads
yt-dlp ....Once there, you can use the yt-dlp command freely.
A reverse proxy can provide additional authentication and/or HTTPS support for YTPTube.
The following example Caddyfile gets a reverse proxy going behind caddy.
# If you are using sub-domain.
# make sure to change "ytptube:8081" to the actual name of your YTPTube container/port.
ytp.example.org {
reverse_proxy ytptube:8081
}
# If you are using sub-folder, for example: https://example.org/ytptube/
# Also make sure to set the `YTP_BASE_PATH` environment variable to `/ytptube/`
# make sure to change "ytptube:8081" to the actual name of your YTPTube container/port.
example.org {
redir /ytptube /ytptube/
route /ytptube/* {
reverse_proxy ytptube:8081
}
}To load yt-dlp plugins in YTPTube, create a folder named yt-dlp inside /config. The path will be /config/yt-dlp.
Follow the yt-dlp plugins docs to install the plugins.
Once you have installed the plugins, restart the container and the plugins will be auto-loaded on demand.
YTPTube can pull random background images from different sources, including WatchState, another project of mine. Set the
YTP_PICTURES_BACKENDS environment variable to the following URL:
YTP_PICTURES_BACKENDS=https://watchstate.ip/v1/api/system/images/background?apikey=[api_key]Where [api_key] is the api key you get from your WatchState instance.
Mounting the share folder as the target for /downloads can cause permission or cross-device link errors. To avoid
these issues, mount the share folder as a named volume, then mount the named volume at /downloads/smb or
/downloads/nfs.
The root compose.yaml contains examples of NFS and SMB mounts and volume definitions. Replace the
server info before enabling them. Keep /config on local storage because SQLite does not support network filesystems.
Important
If you prefer, you can bypass YTPTube download_path and set it to / and completely manage your own mounts. However,
please be aware that the file browser feature will expose whatever download_path is set to. So, if you set it to /,
the file browser will expose the entire container filesystem including the /config directory.
The project first started as a fork meTube, since then it has been completely rewritten and redesigned.
As the container is rootless, we cannot do the necessary changes to the container to enable hardware acceleration.
However, We do have the drivers and ffmpeg already installed and the CPU transcoding should work regardless. To enable
hardware acceleration You need to alter your compose.yaml file to mount the necessary devices to the container. Here
is an example of how to do it for debian based systems.
The root compose.yaml contains the optional device and group settings. Uncomment them and set
VIDEO_GID and RENDER_GID to the corresponding group IDs from the host.
This setup should enable VAAPI encoding in x86_64 containers.
Note
Your video, render group id might be different from mine, you can run the follow command in docker host server
to get the group ids for both groups.
cat /etc/group | grep -E 'render|video'
video:x:44:your_docker_username
render:x:105:your_docker_usernameIn my docker host the group id for video is 44 and for render is 105. change what needed in the compose.yaml
file to match your setup.
If for some reason the initial test for GPU encoding fails, YTPTube will fallback to software encoding. You can force
software encoding by setting the YTP_STREAMER_VCODEC environment variable to libx264. If you want to force GPU
encoding, set the YTP_STREAMER_VCODEC environment variable to one of the supported GPU codecs, for
example h264_vaapi or h264_nvenc depending on your GPU. For the supported codec implementations,
see segment_encoders.py.
Note
If GPU encoding fails and software encoding is used, restart the container before trying GPU encoding again. YTPTube tests GPU encoding only once, when the first video stream starts.
The Docker container builder supports self-hosted repositories such as Gitea. Define two values in your repository settings:
- Create a secret named
GIT_TOKENand set it to your Gitea personal access token. - Create a variable named
REGISTRYand set it to your docker registry, for examplegitea.domain.org.
The main.yml workflow will then disable the Docker/GitHub container registries and use your Gitea repository instead.
The container name will be REGISTRY/ytptube, and the tags will match those used in the GitHub registry.
Unfortunately, the native-builder.yml workflow doesn't support self-hosted repositories at the moment.
If you encounter this error: OSError: [Errno 28] No space left on device This indicates that either
the /tmp or /downloads directory has run out of available space.
This issue commonly occurs when:
/tmpis mounted astmpfs(memory-based storage)- Your system has limited RAM
- You're downloading large video files
Since videos are temporarily stored in /tmp before being moved to the final download location, memory-based storage
may be insufficient for large downloads.
To fix the issue, modify your compose.yaml to use a disk-based directory for temporary files:
Temporary storage Compose example
services:
ytptube:
user: "${UID:-1000}:${UID:-1000}"
image: ghcr.io/arabcoders/ytptube:latest
container_name: ytptube
restart: unless-stopped
ports:
- "8081:8081"
volumes:
- ./config:/config:rw
- ./downloads:/downloads/local:rw
- ./temp:/tmp:rwNote
Replace the tmpfs mount with a local directory volume (./temp:/tmp:rw). This allows temporary files to use disk space instead of RAM.
Restart the container to apply the mount change. Temporary files will then use the mounted disk path instead of RAM.
During YouTube premieres, streams usually contain a loading screen of 1-5 minutes before the actual video content starts playing. By default we wait for 5min + the duration of the video before starting the download to ensure we get the full video without the loading screen. However, you can override the behavior by setting the following environment variable:
YTP_LIVE_PREMIERE_BUFFER=10Where YTP_LIVE_PREMIERE_BUFFER is the buffer time in minutes to add to the video duration before the download starts.
This will help in case the premiere has a longer loading screen than usual.
You need to setup FlareSolverr or a compatible alternative such
as Trawl (which handles newer challenge formats) and then set
the YTP_FLARESOLVERR_URL environment variable to point to your instance. For example:
The root compose.yaml includes FlareSolverr and configures YTPTube to use it.
See the FlareSolverr and Trawl projects.
Use this extractor when a site's media URL only appears after the page runs in a browser. Set YTP_BROWSER_URL to the
HTTP endpoint exposed by a remote Chromium instance:
YTP_BROWSER_URL=http://chrome:9222Select the generic_browser preset for downloads that need it. The preset forces yt-dlp's generic extractor, so do
not use it for sites supported by a dedicated extractor. The extractor waits up to 60 seconds for media. To use a
shorter limit, add this to the CLI options:
--extractor-args "generic:wait=30"If the browser extractor fails, YTPTube falls back to the normal generic extractor.
The root compose.yaml includes Chromium with remote debugging enabled and configures YTPTube to use it.
YTPTube supports multiple languages with RTL support. Currently the following languages are available:
Available languages:
- English (default)
- العربية (Arabic, RTL)
- Français (French)
- 中文 (Chinese)
- 日本語 (Japanese)
Changing the language:
- Open the Settings panel (gear icon in the sidebar).
- Select your preferred language from the Language dropdown.
- The UI updates immediately and your choice is saved in a browser cookie (
ytptube_locale).
Automatic detection:
On first visit, YTPTube attempts to detect your browser's preferred language and switches automatically if a matching translation is available.