Skip to main content
The -o option controls output file names while -P specifies the path where files should be saved. Output templates allow you to dynamically name files based on video metadata.

Basic Usage

Simple Templates

The simplest usage is a literal filename:
# Hard-coded filename (not recommended)
yt-dlp -o "funny_video.mp4" URL

# Default template
yt-dlp URL  # Uses: %(title)s [%(id)s].%(ext)s
Hard-coding file extensions is not recommended as it may break post-processing. Use %(ext)s to use the correct extension automatically.

Template Syntax

Templates use Python string formatting with special sequences:
%(field_name)s
Sequences are replaced with actual values when downloading:
# Template: %(title)s-%(id)s.%(ext)s
# Result: yt-dlp test video-BaW_jenozKc.mp4
yt-dlp -o "%(title)s-%(id)s.%(ext)s" URL

Available Fields

Basic Video Information

  • id - Video identifier
  • title - Video title
  • fulltitle - Video title ignoring live timestamp
  • ext - Video file extension
  • display_id - Alternative identifier
  • description - Video description

Playlist Information

  • playlist - Playlist title or ID
  • playlist_id - Playlist identifier
  • playlist_title - Name of the playlist
  • playlist_index - Position in playlist (padded)
  • playlist_count - Total items in playlist
  • playlist_uploader - Playlist uploader name
  • n_entries - Total extracted items

Media Metadata

  • width - Video width
  • height - Video height
  • fps - Frame rate
  • vcodec - Video codec
  • vbr - Video bitrate

Special Fields

  • webpage_url - URL to the video webpage
  • epoch - UNIX epoch when info was extracted
  • autonumber - Auto-incrementing number (padded to 5 digits)
  • format_id - Format identifier
  • resolution - Textual resolution description
Use -j to see all available fields for a particular URL:
yt-dlp -j URL | jq

Advanced Formatting

Object Traversal

Access nested fields using dot notation:
# Access first tag
yt-dlp -o "%(tags.0)s - %(title)s.%(ext)s" URL

# Access subtitle information
yt-dlp -o "%(subtitles.en.-1.ext)s" URL
Python slicing with colons:
# Characters 3-7 of video ID
yt-dlp -o "%(id.3:7)s.%(ext)s" URL

# All format IDs
yt-dlp --print "%(formats.:.format_id)s" URL

Numeric Formatting

Use Python’s printf-style formatting:
# Pad view count with zeros (5 digits)
yt-dlp -o "%(view_count)05d - %(title)s.%(ext)s" URL
# Result: 00042 - Video Title.mp4

# Playlist index (3 digits)
yt-dlp -o "%(playlist_index)03d - %(title)s.%(ext)s" URL
# Result: 001 - First Video.mp4

Date/Time Formatting

Format dates using > separator with strftime codes:
yt-dlp -o "%(upload_date>%Y)s/%(title)s.%(ext)s" URL
# Result: 2024/Video Title.mp4

Alternatives

Provide fallback fields using , separator:
# Use release_date, fallback to upload_date, default to "Unknown"
yt-dlp -o "%(release_date>%Y,upload_date>%Y|Unknown)s/%(title)s.%(ext)s" URL

Replacement Values

Use & separator to replace non-empty fields:
# Add prefix if chapters exist
yt-dlp -o "%(chapters&has chapters|no chapters)s" URL

# Format title with padding
yt-dlp -o "%(title&TITLE={:>20}|NO TITLE)s.%(ext)s" URL

Default Values

Set defaults for empty fields using | separator:
# Default to "Unknown" if uploader is missing
yt-dlp -o "%(uploader|Unknown)s/%(title)s.%(ext)s" URL

Special Conversions

yt-dlp supports additional format types beyond standard Python:
  • B - Bytes conversion
  • j - JSON (use # for pretty-print, + for Unicode)
  • h - HTML escaping
  • l - Comma-separated list (# for newline-separated)
  • q - Shell-quoted string
  • D - Decimal suffixes like 10M (# to use 1024 as factor)
  • S - Sanitize as filename (# for restricted)
  • U - Unicode normalization (NFC, use # for NFD)
yt-dlp --print "%(filesize)B" URL

Output Paths

Use -P to specify paths for different file types:
# Set base download directory
yt-dlp -P "/path/to/downloads" URL

# Set different paths for different file types
yt-dlp -P "home:/videos" -P "temp:/tmp" -P "subtitle:/subs" URL
Available path types:
  • home - Final download location (default)
  • temp - Temporary/intermediate files
  • subtitle - Subtitle files
  • thumbnail - Thumbnail files
  • description - Description files
  • annotation - Annotation files
  • infojson - Info JSON files

Type-Specific Templates

Set different templates for different file types:
# Different template for thumbnails
yt-dlp -o "%(title)s.%(ext)s" -o "thumbnail:%(title)s/%(title)s.%(ext)s" URL

# Don't write thumbnails at all
yt-dlp --write-thumbnail -o "thumbnail:" URL
Available template types:
  • subtitle
  • thumbnail
  • description
  • infojson
  • pl_thumbnail
  • pl_description
  • pl_infojson
  • chapter
  • pl_video

Practical Examples

yt-dlp -o "%(title)s-%(id)s.%(ext)s" URL
# Output: yt-dlp test video-BaW_jenozKc.webm

Advanced Use Cases

Conditional Prefix

Add playlist index only when available:
yt-dlp -o "%(playlist_index&{} - |)s%(title)s.%(ext)s" URL
# Playlist: 01 - Video.mp4
# Single video: Video.mp4

Hierarchical Organization

yt-dlp -o "%(uploader)s/%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s" PLAYLIST_URL

Course Downloads

yt-dlp -P "~/Courses" \
  -o "%(playlist)s/%(chapter_number)s - %(chapter)s/%(title)s.%(ext)s" \
  COURSE_URL

Split Chapters

yt-dlp --split-chapters \
  -o "chapter:%(title)s/%(section_number)02d - %(section_title)s.%(ext)s" \
  URL

Special Characters

Percent Literals

Use %% for a literal percent sign:
yt-dlp -o "100%% complete - %(title)s.%(ext)s" URL
# Output: 100% complete - Video.mp4

Output to Stdout

Use -o - to output to stdout:
# Stream video to stdout
yt-dlp -o - URL | mpv -

Filename Restrictions

Cross-Platform Compatibility

# ASCII-only filenames
yt-dlp --restrict-filenames -o "%(title)s.%(ext)s" URL

# Windows-compatible filenames
yt-dlp --windows-filenames URL

# Limit filename length
yt-dlp --trim-filenames 150 URL

Sanitization

The S conversion automatically sanitizes filenames:
# Sanitize title for safe filesystem use
yt-dlp -o "%(title)S.%(ext)s" URL

# Restricted sanitization (more aggressive)
yt-dlp -o "%(title)#S.%(ext)s" URL

Getting Actual Filename

Due to post-processing, the actual output filename may differ:
# Get final filename after all processing
yt-dlp --print after_move:filepath URL

# Preview filename before download
yt-dlp --print filename -o "%(title)s.%(ext)s" URL

Common Patterns

Clean Organization

yt-dlp -P "~/Videos" -o "%(uploader)s/%(title)s [%(id)s].%(ext)s"

Archive Format

yt-dlp -o "%(upload_date>%Y-%m-%d)s_%(uploader)s_%(id)s.%(ext)s"

Music Downloads

yt-dlp -x --audio-format mp3 \
  -o "%(artist|uploader)s/%(album|playlist|NA)s/%(track_number)02d - %(title)s.%(ext)s"

Safe Default

yt-dlp -o "%(title).200s [%(id)s].%(ext)s" --restrict-filenames