Playlists & Multi-Video Downloads
fetchit can download entire YouTube playlists, multi-post Threads threads, Instagram carousels, and any URL that yt-dlp recognises as containing more than one video. This guide covers every aspect of playlist handling — from detection and interactive selection to parallel downloading, output structure, and scripting.
How playlist detection works
When you pass a URL to fetchit, it does not assume it is a single video. Instead, it runs a two-phase detection process.
The probing phase
fetchit hands the URL to yt-dlp with the --dump-json flag and inspects the response. The key signal is whether yt-dlp returns an array of entries (a playlist) or a single entry (a standalone video). If the response contains a playlist_id and a non-empty entries array with more than one item, fetchit switches into playlist mode.
The probe extracts the following playlist-level metadata:
- Playlist title — used as the folder name for output
- Playlist ID — internal identifier (e.g.
PL...for YouTube) - Entry count — total number of videos in the playlist
- Per-entry metadata — title, duration, thumbnail, and format availability for each video
- Uploader — channel or creator name
Probing a large playlist (100+ videos) can take several seconds because yt-dlp must fetch metadata for every entry. fetchit shows a spinner with a live count of entries discovered so you know progress is happening.
What triggers playlist mode
Playlist mode activates automatically for any URL that yt-dlp recognises as containing multiple videos. This includes:
| Source | URL pattern | Behaviour |
|---|---|---|
| YouTube playlist | youtube.com/playlist?list=PL... | Full playlist with all entries |
| YouTube channel / user | youtube.com/@ChannelName or youtube.com/c/... | All uploads from the channel |
| YouTube mix | youtube.com/watch?v=...&list=RD... | Auto-generated mix playlist |
| Threads thread | threads.net/@user/post/... (multi-image) | All images/videos in the post |
| Instagram carousel | instagram.com/p/... (multi-media) | All items in the carousel |
| Bilibili series | bilibili.com/...series... | Series episodes |
| Twitch collection | twitch.tv/collections/... | Collection of VODs |
If the URL contains exactly one video, fetchit proceeds in single-video mode and the format picker appears as usual. There is no way to force playlist mode for a single-video URL, and no way to suppress playlist mode for a multi-video URL — detection is automatic.
What is NOT a playlist
The following URL types are intentionally treated as single videos even though they may appear in playlist-like contexts:
| URL type | Reason |
|---|---|
| youtube.com/watch?v=... (single) | Only one video ID — no playlist context |
| youtu.be/... | Short link always points to a single video |
| youtube.com/shorts/... | Shorts are standalone short-form videos |
| instagram.com/reel/... | Reels are single videos, not carousels |
| tiktok.com/@user/video/... | TikTok URLs are always single videos |
| x.com/user/status/... (single media) | Single-video tweets download as one file |
| youtube.com/watch?v=...&list=... | Treats only the specific video unless --playlist flag used |
youtube.com/watch?v=...&list=...), fetchit fetches just that one video by default. To download the full playlist, extract the playlist URL alone (youtube.com/playlist?list=...).Interactive playlist mode
When a playlist is detected and you run fetchit without --best or other scriptable flags, you enter interactive playlist mode. This provides a full TUI experience for reviewing and selecting which items to download.
The checklist interface
After probing completes, fetchit displays a scrollable checklist of every video in the playlist. Each entry shows:
- Index number — the video's position in the playlist (01, 02, 03...)
- Title — the video title as reported by yt-dlp
- Duration — length of the video in MM:SS or HH:MM:SS format
- Checkbox — a
[✓]or[ ]indicator showing selection state
All videos are selected by default. The footer displays the total count and the number of currently selected items (e.g., 15/20 selected).
Navigating the checklist
| Key | Action |
|---|---|
| [↑] / [↓] | Move selection highlight up/down |
| [Space] | Toggle selection of the highlighted item |
| [A] | Select all items |
| [N] | Deselect all items (none) |
| [R] | Invert selection (reverse current selection) |
| [PageUp] / [PageDown] | Scroll by one page |
| [Home] | Jump to the first item |
| [End] | Jump to the last item |
| [Enter] | Proceed to format selection with the current selection |
| [Esc] | Go back to the input screen |
The selection is preserved as you scroll — you can selectively toggle individual videos on and off before committing. This is useful when a playlist contains 50 videos and you only want the 3 relevant ones.
Format selection for multiple videos
After confirming your selection with [Enter], fetchit enters the format picker phase. Unlike single-video mode where you pick one format for one video, here you pick a single format that applies to every selected video in the batch.
The format picker behaves identically to single-video mode — same metadata columns, same sorting, same keyboard shortcuts. However, there are a few important differences:
- The file size column shows the estimated size per video, not the total batch size
- Formats that are not available across all selected videos are flagged with a warning icon
- If a format is unavailable for a particular video, fetchit falls back to the next-best compatible format for that one video and prints a notice
- Chapter toggling and time range clipping apply to every video in the batch uniformly
Batch download progress
Once you select a format, fetchit begins downloading all selected items. The download screen shows:
- Overall progress bar — tracks how many videos are complete out of the total selected (e.g.,
3/10) - Current video progress bar — the per-video download indicator with speed, ETA, and percentage
- Current video title — shown above the progress bar so you know which item is downloading
- Elapsed time — total time since the batch started
- Estimated time remaining — calculated from average download speed and remaining items
When a video finishes, fetchit increments the completed count, logs the saved file path, and immediately starts the next item. There is no pause between downloads unless you press [Esc].
Cancelling a batch
Press [Esc] once to cancel the current video download. The partially downloaded file is deleted and fetchit moves to the next video. Press [Esc] twice quickly to cancel the entire batch — remaining videos are skipped and you return to the format picker.
Scriptable playlist mode
For automation and non-interactive use, fetchit supports downloading playlists entirely from the command line. Every video in the playlist is downloaded automatically with no prompts.
Basic scriptable download
fetchit --best https://www.youtube.com/playlist?list=PL... fetchit --mp3 https://www.youtube.com/playlist?list=PL... fetchit https://www.youtube.com/playlist?list=PL... 1080p
In scriptable mode, the checklist interface is skipped entirely. All videos are selected by default and the specified format is applied uniformly across all entries.
Downloading specific items by index
Use the --items flag to download only specific videos from the playlist. This accepts individual indices, comma-separated lists, and ranges.
fetchit --best --items 1,3,5 https://youtube.com/playlist?list=PL... fetchit --best --items 1-10 https://youtube.com/playlist?list=PL... fetchit --best --items 1-5,8,11-15 https://youtube.com/playlist?list=PL...
| Syntax | Meaning | Example |
|---|---|---|
| N | Single item at index N | --items 5 |
| N,M,O | Multiple specific items | --items 2,7,9 |
| N-M | Range from N to M inclusive | --items 3-8 |
| N-M,P,Q-R | Combination of ranges and singles | --items 1-5,10,12-15 |
Download latest N videos
Use --last to download only the most recent N videos from the playlist. This is useful for catching up on a channel without redownloading everything.
fetchit --best --last 5 https://youtube.com/playlist?list=PL... fetchit --best --last 10 https://youtube.com/playlist?list=PL...
The --last flag selects the final N videos by playlist order, not by upload date. If the playlist is sorted chronologically (newest first), --last 5 grabs the most recent 5 entries. Combined with --reverse, you can control which end of the playlist is targeted.
Reverse order
By default, videos download in playlist order (first to last). Pass --reverse to download from last to first.
fetchit --best --reverse https://youtube.com/playlist?list=PL... fetchit --best --items 1-10 --reverse https://youtube.com/playlist?list=PL...
This is useful when you want the final video in a playlist to finish first — for example, if you are watching in release order but want to save the finale for last.
Combined with other flags
All scriptable-mode flags work with --items, --reverse, and --last:
fetchit --mp3 --items 1-20 https://youtube.com/playlist?list=PL... fetchit --chapters --last 3 https://youtube.com/playlist?list=PL... fetchit --from 5:30 --to 10:15 --items 3,7 https://youtube.com/playlist?list=PL...
When combining --from/--to time ranges with a playlist, the time range is applied to every selected video. Each video is clipped to the same start and end times.
Output directory structure
Playlist downloads use a different output layout than single-video downloads. Instead of saving individual files directly to the output directory, fetchit groups them into a subfolder named after the playlist.
Default structure
~/Downloads/
My Cool Playlist/
01 - First Video.mp4
02 - Second Video.mp4
03 - Third Video.mp4
...Playlist folder naming convention
The folder name is derived from the playlist title returned by yt-dlp, sanitised to remove characters that are invalid on your filesystem:
- Characters
\ / : * ? " < > |are replaced with underscores or removed - Leading and trailing whitespace is trimmed
- If the title is empty or contains only invalid characters, the playlist ID is used as a fallback
- Truncated to 200 characters to avoid
ENAMETOOLONGerrors on Windows
File naming within playlists
Individual files follow a numbered prefix convention to preserve playlist ordering:
{index:02d} - {title} [{id}].{ext}The {index:02d} portion is the video's position in the playlist, zero-padded to at least 2 digits. This ensures alphabetical sorting matches playlist order. For playlists with 100+ items, the padding expands to 3 digits (001).
| Playlist size | Index format | Example |
|---|---|---|
| 1-99 items | {index:02d} | 01 - ... |
| 100-999 items | {index:03d} | 042 - ... |
| 1000+ items | {index:04d} | 1003 - ... |
Custom output directory
Override the parent directory with the -o flag. The playlist subfolder is still created inside the specified path:
fetchit --best -o ~/Videos/Playlists https://youtube.com/playlist?list=PL...
Produces:
~/Videos/Playlists/My Cool Playlist/ 01 - First Video.mp4 02 - Second Video.mp4
Skip the playlist folder
If you prefer all files to land flat in a single directory without playlist grouping, use the --flat flag:
fetchit --best --flat https://youtube.com/playlist?list=PL...
Files are named with the playlist title and index prefix directly:
~/Downloads/My Cool Playlist - 01 - First Video.mp4 ~/Downloads/My Cool Playlist - 02 - Second Video.mp4
Custom output templates
For full control over file naming, use the --output-template flag. This accepts yt-dlp-style output template variables.
Available template variables
| Variable | Description | Example value |
|---|---|---|
| %(playlist_title)s | Title of the playlist | My Cool Playlist |
| %(playlist_id)s | Playlist ID | PL12345ABCDE |
| %(playlist_index)s | Index within the playlist | 3 |
| %(playlist_autonumber)s | Auto-incrementing number across all playlists | 5 |
| %(title)s | Video title | First Video |
| %(id)s | Video ID | abc123def45 |
| %(uploader)s | Channel or creator name | Channel Name |
| %(duration)s | Duration in seconds | 245 |
| %(ext)s | File extension | mp4 |
| %(resolution)s | Video resolution | 1920x1080 |
Template examples
# Default template fetchit --best --output-template "%(playlist_index)02d - %(title)s [%(id)s].%(ext)s" https://... # Include uploader fetchit --best --output-template "%(uploader)s - %(title)s.%(ext)s" https://... # Full path template fetchit --best --output-template "%(playlist_title)s/%(playlist_index)02d - %(title)s.%(ext)s" https://... # Custom folder with channel fetchit --best --output-template "YouTube/%(uploader)s/%(playlist_title)s/%(title)s.%(ext)s" https://...
When using a template that includes %(playlist_title)s in a path component, the same sanitisation rules apply as for the default folder naming. If the template omits %(playlist_index)s, files are still named with the index prefix to preserve order.
Concurrency and parallel downloads
fetchit downloads playlist items concurrently to maximise throughput. By default, up to 3 videos download simultaneously.
Why parallel?
Sequential downloading (one video at a time) underutilises your network connection, especially for short videos where the overhead of probing and negotiation dominates. Parallel downloads keep the pipeline full and reduce total batch time significantly.
Default behaviour
The default concurrency is 3 concurrent downloads. This strikes a balance between speed and reliability on most consumer internet connections. Each download runs in its own yt-dlp process with independent progress tracking.
Tuning concurrency
fetchit --best --concurrency 5 https://youtube.com/playlist?list=PL... fetchit --best --concurrency 1 https://youtube.com/playlist?list=PL... # sequential
| Concurrency | Use case |
|---|---|
| 1 | Sequential — minimum bandwidth usage, polite to the server |
| 3 | Default — balanced throughput for typical home connections |
| 5 | Aggressive — fast on high-bandwidth connections (>100 Mbps) |
| 10+ | Maximum speed — only if you have a very fast connection and the server allows it |
YouTube throttling
YouTube intentionally throttles parallel connections to the same stream. When you download multiple videos from the same YouTube playlist simultaneously, each video comes from a different CDN edge server, so the throttling is per-stream rather than global. However, YouTube may still rate-limit your IP if you open too many concurrent connections.
In practice, concurrency values above 5 rarely improve total download time on YouTube. If you see individual download speeds dropping as concurrency increases, you have hit YouTube's per-IP limit. Reduce --concurrency or use a VPN to distribute across different IPs.
For non-YouTube sources (Threads, Instagram, direct video hosts), higher concurrency values are often more effective because these platforms do not enforce the same per-IP limits. Experiment with --concurrency 8 or higher for these sources.Monitoring concurrent downloads
In interactive mode, fetchit shows separate progress bars for each active download, stacked vertically. Each bar includes the video title, percentage, speed, and ETA. Completed bars collapse into a summary line. In scriptable mode, the output is line-based with each download completing on its own line.
Metadata embedding in batch
When downloading playlists, fetchit embeds additional metadata into each file to help media organisers identify the content.
What gets embedded
| Metadata field | Source | Example |
|---|---|---|
| Playlist title | yt-dlp playlist metadata | My Cool Playlist |
| Track number | Playlist index | 3/20 |
| Track total | Total playlist size | 20 |
| Video title | Per-video metadata | First Video |
| Uploader | Channel / creator name | Channel Name |
| Upload date | Video publish date | 2025-12-01 |
| Description | Video description (truncated) | In this video we... |
This metadata is written as standard MP4/MKV tags, which media servers like Plex, Jellyfin, and Emby can read. For audio files, iTunes-style metadata tags are used so playlists appear correctly in music library applications.
Enabling chapter embedding
Add the --chapters flag to embed chapter markers in every downloaded video:
fetchit --best --chapters https://youtube.com/playlist?list=PL...
Each video's chapters are embedded independently. This is useful for lecture playlists, podcast episodes, or any content with internal section markers.
Combining playlists with other flags
All of fetchit's single-video flags work with playlist downloads. Here are the most useful combinations:
Audio extraction
# Download entire playlist as MP3 fetchit --mp3 https://youtube.com/playlist?list=PL... # Download first 10 as MP3 fetchit --mp3 --items 1-10 https://youtube.com/playlist?list=PL... # Download last 5 as audio with chapters fetchit --mp3 --chapters --last 5 https://youtube.com/playlist?list=PL...
Best quality batch
fetchit --best https://youtube.com/playlist?list=PL... fetchit --best --concurrency 5 https://youtube.com/playlist?list=PL... fetchit --best --reverse https://youtube.com/playlist?list=PL...
Time range clipping across a playlist
# Clip first 2 minutes of every video in the playlist fetchit --to 2:00 https://youtube.com/playlist?list=PL... # Clip specific section from each of the first 3 videos fetchit --from 1:00 --to 3:30 --items 1-3 https://youtube.com/playlist?list=PL...
When using time ranges with playlists, the range is applied uniformly. You cannot specify different ranges for different items in a single command.
Chapters in batch
fetchit --best --chapters https://youtube.com/playlist?list=PL... fetchit --mp3 --chapters --items 5-15 https://youtube.com/playlist?list=PL...
--best and --mp3 are mutually exclusive. You cannot combine them in a single command. If you need some videos in MP3 and others as video, run two separate commands with --items targeting different indices.Supported playlist sources
fetchit inherits playlist support from yt-dlp, which recognises playlists on hundreds of sites. Here are the most commonly used sources:
YouTube
Full support for public playlists, unlisted playlists (if you have the link), channel upload feeds, mixes, and music playlists. Private playlists require passing browser cookies via --cookies-from-browser. YouTube rate-limits heavy playlist downloads — see the limitations section below.
Threads threads
Threads posts that contain multiple images or videos are treated as a playlist. Each media item is a separate entry. This is useful for saving entire photo dumps or multi-video threads at once.
Instagram carousels
Instagram posts with multiple images or videos (carousels) are detected as playlists. Each carousel item is a separate entry. This works for both feed posts and story highlights.
Other supported sources
| Source | Playlist type | Notes |
|---|---|---|
| Bilibili | Series / collection | Episode series and user-created collections |
| SoundCloud | Sets / playlists | Audio playlists, albums, and user sets |
| Twitch | Collections | Curated collections of VODs |
| Vimeo | Albums / showcases | Curated video albums and showcases |
| Dailymotion | Playlists | User-created playlists and channel feeds |
| Watch playlists | Public video playlists from pages |
Limitations and known issues
YouTube rate limiting
Downloading large playlists from YouTube triggers rate-limiting after 30-50 videos in a short period. YouTube displays a "Sign in to confirm you're not a bot" page. Mitigations:
- Use
--cookies-from-browser firefoxto pass authenticated cookies (Firefox strongly preferred on Windows — Chrome and Edge encrypt cookies) - Reduce concurrency to 1 or 2 to appear less aggressive
- Add a delay between items — fetchit does not yet have a built-in delay flag, but you can wrap it in a shell loop with
sleep - Use a VPN to distribute requests across different IPs for very large batch downloads
- If rate-limited, wait 24-48 hours for the flag to reset
Very large playlists
Playlists with more than 200 entries can be slow to probe because yt-dlp fetches metadata for every entry upfront. The probe time scales roughly linearly with the number of entries. For playlists exceeding 500 entries, consider:
- Using
--last Nto probe only the most recent N items - Breaking the download into multiple commands with
--itemsranges - Monitoring progress via the terminal output
Mixing formats across items
When a selected format is not available for some videos in the batch, fetchit falls back to the best available format for those items. This means you may get inconsistent quality across your downloaded playlist. The fallback is logged but not visually prominent in the TUI.
Memory usage
fetchit keeps all entry metadata in memory during a playlist download. For extremely large playlists (1000+ entries), memory usage can reach 100-200 MB. This is typically not an issue on modern machines but may be noticeable on low-memory systems.
Unicode and special characters
Some playlist and video titles contain emoji, CJK characters, or other Unicode that may not display correctly in all terminals. File names are sanitised for the filesystem, but the interactive checklist displays the raw title as reported by yt-dlp. If you see garbled characters, the source metadata contains encoding that your terminal does not support.
No progress for individual items in scriptable mode
In scriptable mode (--best, --mp3, etc.), fetchit outputs one line per completed video rather than showing real-time progress bars. The output includes the file path and file size after each item finishes. If you need per-video progress visibility, use interactive mode.
Real-world examples
Download a music album playlist as MP3
fetchit --mp3 --concurrency 3 --chapters \ https://music.youtube.com/playlist?list=OLAK5uy_...
This downloads an entire YouTube Music album, converts each track to MP3, embeds chapter markers, and saves them to ~/Downloads/{Album Title}/.
Download specific lectures from a course playlist
fetchit --best --items 3,7,12-15 --concurrency 2 \ https://youtube.com/playlist?list=PL...
Selects only lectures 3, 7, and 12 through 15 from a large course playlist, downloading them at best quality with 2 concurrent streams.
Save a Threads photo dump
fetchit --best --flat --output-template "%(playlist_index)02d - %(title)s.%(ext)s" \ https://www.threads.net/@username/post/...
Downloads all images and videos from a multi-media Threads post into a flat directory with numbered filenames.
Download the latest podcast episodes
fetchit --mp3 --last 5 --chapters --concurrency 1 \ https://youtube.com/playlist?list=PL...
Grabs the 5 most recent episodes from a podcast playlist, extracting audio with chapters and downloading sequentially to avoid rate limits.
Convert an entire playlist to audio with custom output
fetchit --mp3 --output-template "%(uploader)s/%(playlist_title)s/%(playlist_index)02d - %(title)s.%(ext)s" \ -o "D:/Music" \ https://youtube.com/playlist?list=PL...
Produces:
D:/Music/Channel Name/My Playlist/01 - First Track.mp3 D:/Music/Channel Name/My Playlist/02 - Second Track.mp3
Download in reverse order for chronological viewing
fetchit --best --reverse --concurrency 1 \ https://youtube.com/playlist?list=PL...
Downloads the playlist from last to first, one at a time. Useful when a playlist is sorted newest-first but you want to watch in chronological (oldest-first) order and download the file you will watch next.
Quick check for how many videos are in a playlist
Use the --dry-run flag to see what would be downloaded without actually downloading anything:
fetchit --best --dry-run https://youtube.com/playlist?list=PL... fetchit --best --items 1-5 --dry-run https://youtube.com/playlist?list=PL...
This prints the playlist title, total entry count, and a list of all video titles and indices that would be downloaded. No files are written.
See also
- Interactive Mode — keyboard and mouse reference for the TUI
- Scriptable Mode — command-line flags and automation guide
- Troubleshooting — common issues and solutions for all download types