This document provides a comprehensive reference for all configuration options in Youtarr's config.json file.
These settings can be changed from the Configuration page in the web UI.
- Configuration File Location
- Core Settings
- Plex Integration
- SponsorBlock Settings
- Kodi, Emby and Jellyfin Compatibility
- Cookie Config
- Notifications
- Download Performance
- Advanced Settings
- Auto-Removal Settings
- API Keys & External Access
- Account & Security
- System Fields
- Configuration Examples
- Best Practices
- Troubleshooting
The configuration file is stored at ./config/config.json relative to your Youtarr installation directory.
The config.json is automatically created on first startup if it doesn't exist, with sensible defaults from config.example.json.
Configuration can be modified through:
- Web UI (recommended) - Configuration page in the application
- Manual editing - Stop Youtarr, edit the JSON file, restart
- Environment variables - Some values can be overridden (see ENVIRONMENT_VARIABLES.md)
- Config Key: This can only be set via .env and is view only in the web UI
- Type:
string - Default:
"./downloads" - Description: Directory path for downloaded videos
- Note: Set during initial setup or via YOUTUBE_OUTPUT_DIR environment variable
- Config Key:
channelAutoDownload - Type:
boolean - Default:
false - Description: Automatically download most recent videos from auto-download enabled channels and tabs
- Note: When true, the newest videos automatically downloaded on a cron schedule
- Config Key:
channelDownloadFrequency - Type:
string(cron expression) - Default:
"0 * * * *"(hourly) - Description: Cron schedule for automatic channel refreshes and downloads
- Examples:
"0 */6 * * *"- Every 6 hours"0 2 * * *"- Daily at 2 AM"0 0 * * 0"- Weekly on Sunday at midnight"*/30 * * * *"- Every 30 minutes
- Config Key:
channelFilesToDownload - Type:
number - Default:
5 - Description: Maximum number of most recent videos to download per channel per scheduled auto download
- Range: 1-10
- Note: Applies to scheduled autodownloads and manually triggered channel downloads
- Config Key: preferredResolution
- Type:
string - Default:
"1080" - Options:
"4320","2160","1440","1080","720","480","360","240","144" - Description: Global setting for preferred download resolution
- Note: Downloads from YouTube at best available quality up to this limit
- Config Key:
videoCodec - Type:
string - Default:
"default" - Options:
"default","h264","h265" - Description: Preferred video codec for downloads, default generally downloads as vp9 or av1
- Compatibility:
h264: Best compatibility with all devicesh265: Better compression, requires modern devicesvp9: YouTube's preferred codecav1: Best compression, limited device support
- Config Key:
defaultSubfolder - Type:
string - Default:
""(empty - downloads to root directory) - Description: Default download location for untracked channels and channels set to use "Default Subfolder"
- Note: Subfolders are prefixed with
__on the filesystem (e.g., settingSportscreates__Sports/) - Channel Subfolder Semantics:
- "Default Subfolder" (NULL in database): Channel uses this global default setting
- "No Subfolder" (special value): Channel explicitly downloads to root directory, ignoring the global default
- Specific subfolder: Channel downloads to that specific subfolder
- Use Cases:
- Organize untracked manual downloads into a specific folder
- Set a default location while allowing individual channels to override
- Explicitly place specific channels in the root directory using "No Subfolder"
- Config Key:
subtitlesEnabled - Type:
boolean - Default:
false - Description: Download subtitles/closed captions with videos
- Config Key:
subtitleLanguage - Type:
string - Default:
"en" - Description: Preferred subtitle language(s) when downloading subtitle files for videos (ISO 639-1 code)
- Examples:
"en"(English),"es"(Spanish),"fr"(French) - Note: Only displayed when subtitles are enabled
- Config Key:
darkModeEnabled - Type:
boolean - Default:
false - Description: Enable dark mode in web UI
- Config Key:
plexApiKey - Type:
string - Default:
""(empty) - Description: Plex authentication token (X-Plex-Token)
- Note: Can be obtained through Plex OAuth in the web UI or manually entered
- Config Key:
plexYoutubeLibraryId - Type:
string - Default:
""(empty) - Description: Plex library section ID for YouTube videos
- Note: Library refresh is automatically triggered if configured when new videos are downloaded
- Config Key:
plexIP - Type:
string - Default:
""(empty) - Description: Plex server IP address or hostname
- Examples:
"192.168.1.100","host.docker.internal"
- Config Key:
plexPort - Type:
string - Default:
"32400" - Description: Plex server port number
- Config Key:
plexViaHttps - Type:
boolean - Default:
false - Description: Use HTTPS for Plex connections
- Note: Enable for remote Plex servers or when SSL is configured
- Config Key:
plexUrl - Type:
string - Default:
""(empty) - Description: Optional full Plex base URL (e.g.,
https://plex.example.com:32400) - Usage: Not configurable via the web UI. Edit
config/config.jsonmanually or set thePLEX_URLenvironment variable to populate it. - Note: When this field is set it takes precedence over the
plexIP,plexPort, andplexViaHttpsvalues shown in the UI.
- Config Key:
sponsorblockEnabled - Type:
boolean - Default:
false - Description: Enable SponsorBlock to skip/remove sponsored segments
- Config Key:
sponsorblockAction - Type:
string - Default:
"remove" - Options:
"remove","mark" - Description: How to handle sponsored segments
remove: Cut segments from video filemark: Add chapters to mark segments
- Config Key:
sponsorblockCategories - Type:
object - Default:
{
"sponsor": true,
"intro": false,
"outro": false,
"selfpromo": true,
"preview": false,
"filler": false,
"interaction": false,
"music_offtopic": false
}- Description: Which segment types to skip/remove
- Config Key:
sponsorblockApiUrl - Type:
string - Default:
""(uses default SponsorBlock API) - Description: Custom SponsorBlock API server URL (optional)
- Example:
"https://sponsor.ajay.app"
- Config Key:
writeChannelPosters - Type:
boolean - Default:
true - Description: Generate channel poster images for media servers
- Note: Creates poster.jpg in each channel directory
- Config Key:
writeVideoNfoFiles - Type:
boolean - Default:
true - Description: Generate NFO metadata files for Kodi/Jellyfin/Emby
- Note: Creates .nfo XML files with video metadata
- Config Key:
cookiesEnabled - Type:
boolean - Default:
false - Description: Use cookies for YouTube authentication
- Note: May be required in some cases to get around YouTube bot detection
- Config Key:
customCookiesUploaded - Type:
boolean - Default:
false - Description: Indicates if custom cookies.txt file has been uploaded
- Note: Managed automatically by the application
Youtarr uses Apprise to send notifications when new videos are downloaded, supporting 100+ notification services.
- Config Key:
notificationsEnabled - Type:
boolean - Default:
false - Description: Enable notifications when new videos are downloaded
- Config Key:
appriseUrls - Type:
arrayof objects - Default:
[](empty array) - Description: List of notification service configurations
Each entry in the array is an object with the following properties:
| Property | Type | Description |
|---|---|---|
url |
string |
Apprise-compatible notification URL |
name |
string |
Friendly name for this notification (e.g., "Discord - Gaming Server") |
richFormatting |
boolean |
Enable rich formatting (embeds, styled text) when supported |
Example Configuration:
{
"appriseUrls": [
{
"url": "discord://webhook_id/webhook_token",
"name": "Discord Server",
"richFormatting": true
},
{
"url": "tgram://bot_token/chat_id",
"name": "Telegram Group",
"richFormatting": true
},
{
"url": "ntfy://my-topic",
"name": "Ntfy Mobile",
"richFormatting": false
}
]
}For supported services, Youtarr sends beautifully formatted notifications with embeds, styled text, video cards, and timestamps. Services without rich formatting support receive plain text notifications.
| Service | URL Format | Rich Formatting |
|---|---|---|
| Discord | discord://webhook_id/webhook_token |
✅ Embeds with colors, thumbnails |
| Telegram | tgram://bot_token/chat_id |
✅ HTML formatting |
| Slack | slack://token_a/token_b/token_c |
✅ Block Kit formatting |
mailto://user:pass@gmail.com |
✅ HTML email with styling | |
| Pushover | pover://user_key@app_token |
❌ Plain text |
| Ntfy | ntfy://topic |
❌ Plain text |
| Other services | Various | ❌ Plain text |
Toggle "Rich formatting" off on any webhook to send plain text instead.
Apprise supports 100+ notification services. See the Apprise Notification Services Wiki for a complete list and URL formats.
Common services include:
- Discord:
discord://webhook_id/webhook_token - Telegram:
tgram://bot_token/chat_id - Slack:
slack://token_a/token_b/token_c - Pushover:
pover://user_key@app_token - Ntfy:
ntfy://topicorntfys://your-server/topic - Email:
mailto://user:pass@gmail.com - Matrix:
matrix://user:pass@hostname/#room - Gotify:
gotify://hostname/token
If you previously used the discordWebhookUrl configuration option, Youtarr automatically migrates it to the new appriseUrls format on startup:
Before (legacy):
{
"discordWebhookUrl": "https://discord.com/api/webhooks/123/abc",
"notificationService": "discord"
}After (automatic migration):
{
"appriseUrls": [
{
"url": "https://discord.com/api/webhooks/123/abc",
"name": "Discord Webhook",
"richFormatting": true
}
]
}The old discordWebhookUrl and notificationService fields are automatically removed after migration. No manual action is required.
- Config Key:
downloadSocketTimeoutSeconds - Type:
number - Default:
30 - Description: Network timeout for download connections (seconds)
- Range: 10-300
- Note: Corresponds to yt-dlp
--socket-timeoutsetting. Time to wait before giving up, in seconds.
- Config Key:
downloadThrottledRate - Type:
string - Default:
"100K" - Description: Bandwidth limit for downloads
- Examples:
"500K","1M","10M",""(unlimited) - Note: Corresponds to yt-dlp
--throttled-ratesetting. Minimum download rate in bytes per second below which throttling is assumed and the video data is re-extracted.
- Config Key:
downloadRetryCount - Type:
number - Default:
2 - Description: Number of retry attempts for failed downloads
- Range: 0-10
- Note: Used for yt-dlp
--fragment-retriesand--retriessettings.
- Config Key:
enableStallDetection - Type:
boolean - Default:
true - Description: Detect and abort stalled downloads
- Note: Setting to control whether stall detection window and rate threshold are used.
- Config Key:
stallDetectionWindowSeconds - Type:
number - Default:
30 - Description: Time window for stall detection (seconds)
- Config Key:
stallDetectionRateThreshold - Type:
string - Default:
"100K" - Description: Minimum download rate before considering stalled
- Config Key:
sleepRequests - Type:
number - Default:
1 - Description: Delay between YouTube API requests (seconds)
- Note: Corresponds to yt-dlp
--sleep-requestssetting.
- Config Key:
proxy - Type:
string - Default:
""(empty) - Description: HTTP/HTTPS proxy for downloads
- Format:
"http://proxy:port"or"socks5://proxy:port" - Note: The proxy is used by yt-dlp for all YouTube requests (downloads, metadata, thumbnails). Some operations like thumbnail downloads and RSS feed checks first attempt a direct HTTP request with a 15-second timeout before falling back to yt-dlp. SOCKS5 proxy users may notice brief delays (~15 seconds) during these fallbacks when adding or refreshing channels, but the operations will complete successfully via yt-dlp.
- Config Key:
useTmpForDownloads - Type:
boolean - Default:
false - Description: Controls where downloads are staged before moving to final location:
false(default): Downloads are staged in a hidden.youtarr_tmp/directory within your output folder. Uses fast atomic renames since source and destination are on the same filesystem. The dot-prefix hides in-progress downloads from media servers like Plex and Jellyfin.true: Downloads are staged in the external path specified bytmpFilePath(e.g.,/tmp). Useful when your output directory is on slow network storage and you want to download to fast local storage first.
- Note: Some managed platforms (e.g., ElfHosted) force this value on.
- Config Key:
tmpFilePath - Type:
string - Default:
"/tmp/youtarr-downloads" - Description: External temporary directory for downloads when
useTmpForDownloadsistrue - Note: Only used when
useTmpForDownloadsis enabled. Internal path in Youtarr container.
If your output directory (YOUTUBE_OUTPUT_DIR) is on an NFS mount, be aware of the following:
When useTmpForDownloads: true: Downloads are staged on a different filesystem from the output directory. The move from temp to output is a cross-filesystem copy+delete, which is vulnerable to NFS stale mount errors. If the NFS mount goes stale, downloads succeed to the temp dir but fail during the move phase. Critically, yt-dlp marks the video as "downloaded" in its archive before the move, so the video becomes permanently stuck — it won't be retried on the next scheduled run because yt-dlp thinks it already succeeded.
Recommended NFS mount options: If using NFS, mount with options that prevent stale file handles:
server:/export /mnt/nfs-output nfs hard,intr,actimeo=3,timeo=300,retrans=5 0 0
hard— retries NFS operations indefinitely instead of failing immediatelyintr— allows signals to interrupt hung NFS operationsactimeo=3— refreshes NFS attribute cache every 3 seconds (default 60s can cause stale metadata)timeo=300,retrans=5— longer timeouts before declaring failure
Docker native NFS volumes (recommended): Instead of bind-mounting a host NFS directory, let Docker mount NFS directly. This is more resilient because Docker manages the NFS connection rather than inheriting a potentially-stale host mount:
services:
youtarr:
volumes:
- youtube-data:/usr/src/app/data # named NFS volume
- ./server/images:/app/server/images
- ./config:/app/config
- ./jobs:/app/jobs
volumes:
youtube-data:
driver: local
driver_opts:
type: nfs
o: addr=YOUR_NFS_SERVER_IP,hard,intr,nfsvers=4,actimeo=3
device: ":/path/to/your/nfs/export"Simplest workaround: Set useTmpForDownloads: false (the default). Downloads are staged inside the output directory itself, so the move is a same-filesystem rename — atomic and immune to this class of error. Note: if the NFS mount is stale, downloads will still fail, but they will fail before yt-dlp marks them as archived — so they'll be automatically retried on the next scheduled run rather than getting permanently stuck.
- Config Key:
autoRemovalEnabled - Type:
boolean - Default:
false - Description: Enable automatic deletion of old videos
- Config Key:
autoRemovalFreeSpaceThreshold - Type:
string - Default:
null(not set) - Description: Minimum free space to maintain
- Examples:
"100GB","500GB","1TB" - Note: Deletes oldest videos when space falls below threshold
- Config Key:
autoRemovalVideoAgeThreshold - Type:
string - Default:
null(not set) - Description: Delete videos older than this age
- Examples:
"30d"(30 days),"3m"(3 months),"1y"(1 year)
Settings for API key authentication used by bookmarklets, mobile shortcuts, and automation tools.
- Config Key:
apiKeyRateLimit - Type:
number - Default:
10 - Description: Maximum download requests per minute per API key
- Range: 1-100
- Note: Helps prevent abuse from external integrations. Each API key is rate-limited independently.
For detailed information on creating and using API keys, see API Integration Guide.
- Type:
string - Default: Not set (must be configured)
- Description: Login username for the web interface
- Validation: 3-32 characters, no leading/trailing spaces
- Note: Set during initial setup or via AUTH_PRESET_USERNAME environment variable
- Type:
string - Default: Not set (must be configured)
- Description: Bcrypt hash of the login password
- Note: Never edit directly - use web UI or AUTH_PRESET_PASSWORD environment variable
These fields are managed automatically by the application:
Type: string
Default: Auto-generated
Description: Unique installation identifier
Note: Currently unused
See config/config.example.json
- Backup your config.json before major changes
- Use the Web UI for configuration when possible
- Test cron expressions at crontab.guru
- Monitor disk space when enabling auto-downloads
- Start conservative with download frequency to avoid rate limiting
- Check file permissions:
ls -la config/config.json - Ensure proper ownership matches YOUTARR_UID/GID
- Check logs for write permission errors
- Clear browser cache
- Ensure you're running the latest version
- Check browser console for JavaScript errors
- Verify cron expression syntax
- Check timezone setting (TZ environment variable)
- Review logs for scheduler errors