April 5Apr 5 ChannelHoarder is a self-hosted video channel archiver with a modern web UI. It monitors channels across YouTube, Rumble, Twitch, Dailymotion, Vimeo, and Odysee and automatically downloads new videos in Plex-compatible format - all inside a single Docker container.GitHub: https://github.com/sworcery/ChannelHoarderDocker Image: ghcr.io/sworcery/channelhoarder:latestHow It WorksAdd a channel URL or playlist, and ChannelHoarder will scan it for videos and queue them for download. New videos are checked on a configurable schedule (default: 3 AM daily). Downloaded videos are organized in Plex TV Show format - each channel is a "show", each year is a "season", and videos are numbered as episodes in upload order. Point your Plex TV Shows library at the download folder and everything just works.Episode ManagementSonarr-style episode handling with per-episode monitored/unmonitored toggles, colored status icons, collapsible season groups with per-season actions, quality cutoff with upgrade detection, and a per-episode action menu (re-download, rename, delete file, skip).AuthenticationChannelHoarder includes a built-in PO token server so most YouTube videos download without any account or cookies. When cookies are available they take priority over PO tokens. For cookie management you have three options:Upload a cookies.txt file manually through the Settings pageUse the included Tampermonkey userscript - install it from Settings for automatic browser cookie syncUse the Firefox cookie exporter script for scheduled cookie refresh on a Windows machineFeaturesAutomatic channel scanning and downloading on a configurable schedulePlaylist support - add YouTube playlists by URLPlex-compatible TV Show naming (Channel / Season Year / S01E01 - Title)Monitored/unmonitored per episode with bulk actionsSonarr-style status icons (downloaded, missing, queued, failed, skipped)Collapsible season groups with per-season download and monitor controlsQuality cutoff with upgrade detection and searchPer-episode file management (re-download, rename, delete file, skip)Auto-download toggle - browse a channel before downloadingSubtitle/caption download supportMinimum duration filter per channelBuilt-in PO token server - no YouTube account requiredSmart auth - cookies take priority over PO tokens when availableYouTube Shorts detection and filteringReal-time download progress via WebSocketPer-channel quality settings (best, 1080p, 720p, 480p)Per-channel custom download directoriesStandalone video download by URL (no channel required)Import existing video libraries with fuzzy title matchingTelegram and Pushover notificationsMulti-platform: YouTube, Rumble, Twitch, Dailymotion, Vimeo, OdyseeError diagnostics with classification and suggested fixesAnti-detection settings (configurable delays, jitter, user-agent rotation)In-app help links to documentationConfig import/export for backup and migrationDark and light modePlex SetupAdd your downloads folder as a TV Shows library in Plex. ChannelHoarder generates tvshow.nfo and episode .nfo metadata files along with poster images and season posters so channels appear with proper artwork and descriptions. Since these are YouTube channels and not traditional TV shows, Plex won't find metadata from its online sources - you may need to set the library agent to "Personal Media" or manually edit show/episode metadata like descriptions and artwork to your liking.RequirementsDocker and Docker Compose50 GB+ disk space (plan 500 MB - 1 GB per video at best quality)Post here for support, bug reports, or feature requests. Edited April 10Apr 10 by sworcery
April 6Apr 6 Database creation step during initial run fails:sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: channels[SQL: ALTER TABLE channels ADD COLUMN platform VARCHAR(32) DEFAULT 'youtube' NOT NULL](Background on this error at: https://sqlalche.me/e/20/e3q8)Database initialization failedClearing DB and rebuilding does not resolve issue. Fresh install using CA template. CA template is setup by default to create 2 appdata folders (appdata/channelhoarder/cookies and appdata/ChannelHoarder/db-files). Only changes to my install are to join the appdata folders under appdata/channelhoarder/I'm very interested in running this docker! I appreciate your support!
April 6Apr 6 Author 3 hours ago, alicecantsleep said:Database creation step during initial run fails:sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: channels[SQL: ALTER TABLE channels ADD COLUMN platform VARCHAR(32) DEFAULT 'youtube' NOT NULL](Background on this error at: https://sqlalche.me/e/20/e3q8)Database initialization failedClearing DB and rebuilding does not resolve issue. Fresh install using CA template. CA template is setup by default to create 2 appdata folders (appdata/channelhoarder/cookies and appdata/ChannelHoarder/db-files). Only changes to my install are to join the appdata folders under appdata/channelhoarder/I'm very interested in running this docker! I appreciate your support!Thanks for reporting this! I found the bug and just pushed a fix in v1.4.4. The database initialization was missing a required import, so tables never got created on fresh installs.To fix it, just update the container:Go to the Docker tab in UnraidClick the ChannelHoarder icon and select "Force Update"Start the containerIf the old database file is still there from the failed attempts, delete it first: remove everything in your /config appdata folder before starting the updated container so it gets a clean slate.Let me know if you run into anything else!
April 6Apr 6 Excellent! Up and running! Can't wait to dig in!Feature Request: Playlist support Edited April 6Apr 6 by alicecantsleep Added Feature Request to previous post instead of a new post to reduce channel clutter.
April 9Apr 9 Loving this so far! This is fitting nearly all of my YT download needs from channel backup to individual file downloads. And it's so much better than the implementation and scripting I was working on! Thanks for all your hard work! A few feature requests/suggestions/ideas:ADDPlaylist supportAbility to unmonitor all episodes prior to adding/scanning channelAutomated show poster generation using channel logo?Automated season poster generation based on name/year?Ability to delete individual episodes from webui - deleting video, nfo, and image when doneFIXAbility to skip episodes that are already in download queue - mine force download anyway and I have to delete them through my file managerChannel logo not loading in webgui - the banners are loading (shown when you click on a channel)Episode ordering/numbering - I've had a strange issue on one of my channels where the numbering is just .... weird. See attached.When a video fails to download it immediately invalidates the cookies, even if they were uploaded only moments ago leading to a looping error of uploading cookies, attempting download, fails, invalidates cookies, repeat. Edited April 10Apr 10 by alicecantsleep
April 10Apr 10 Author @alicecantsleep Thanks again for the detailed feedback! I've pushed v1.7.0 that addresses your list.Bug Fixes:Episode numbering - Episodes are now numbered chronologically by upload date within each year (oldest = E001). There's also a new "Fix Episode Numbers" button on each channel's detail page that lets you preview what would change and apply the fix, including renaming files on disk.Skip queued episodes - You can now skip videos that are already in the download queue.Cookie invalidation loop - Fixed the issue where a failing download would immediately invalidate freshly uploaded cookies.Livestream detection - Upcoming livestreams are now automatically skipped instead of retrying.New Features:Playlist support - You can now add YouTube playlist URLs directly (e.g. https://www.youtube.com/playlist?list=PLxxxx).Delete individual episodes - Each video in the channel detail page now has a delete button (trash icon) that removes the video, NFO, and thumbnail from disk.Auto-download toggle - When adding a channel, uncheck "Auto-download new videos" to browse the channel first without automatically queuing everything. This persists for future scans too.Season posters - Plex season poster images are now automatically created in each Season folder.Channel logo - Can you give me more details on this one? Is it showing a gray placeholder? Which channel does it happen on?The channel logo/thumbnail issue is now fixed in v1.7.1. The logos are now fetched via the YouTube Data API instead of yt-dlp (which was returning 404 errors for channel pages). If you have a YouTube API key configured in Settings, all existing channels will have their thumbnails backfilled automatically on the next container restart.Update your container to v1.7.0 to get everything. Let me know how it goes! Edited April 10Apr 10 by sworcery
April 10Apr 10 HOLY SMOKES! YAAAASSSS! I figured you'd get a few of them but not my whole list! This is amazing work! Thank you! I will for sure put it through it's paces!I'm so blown away! Best container maintainer/dev ever!
April 10Apr 10 Testing V1.7.0I'm an unemployed IT professional so I have time to test 😁====================================================Channel Icons - Confirmed Working ProperlyAuto Download Toggle - CWPEpisode Deletion in WebUI with file cleanup - CWPSeason Posters - still testingCookie Invalidation Loop - still testingPlaylist Support - allows me to enter a playlist url and it pulls the name of the playlist, but does not index any of the videos within. Episode Renamer - seems to work but I'm having an issue with plex not recognizing the nfo files afterwards. Something is strange there. When I analyze a simple 2 episode season that it renamed I found the attached screenshot. It seems there are .info.json files with the old names left behind. I'm not sure if this is causing plex to have problems matching the nfo files after the rename though as the nfo files themselves are properly renamed. I'm still testing. Update ideas:Channel percentages should be 100% if episodes are skipped but the rest is complete.Filesize limit to cull shorts posted on wide video, trailers, and teasers. (I've noticed channels posting shorts on main and these are always measured in MB so I generally already delete ones that are less than 1gb for most of my monitored channels. While I was intending to just write a script real quick to do this, I also thought it might be useful for others who use this docker.) Edited April 10Apr 10 by alicecantsleep Added update ideas.
April 10Apr 10 Author @alicecantsleep Great testing, really appreciate the thorough feedback! Pushed v1.7.2 with fixes for both issues you found:Fixed:Playlist scanning - Playlists now properly index all videos within. Previously it was only pulling the playlist name but not discovering the videos.Episode renamer orphan files - .info.json files are now renamed alongside the .mp4, .nfo, and thumbnail files. The leftover files you saw with the old names should no longer happen on future renames.Also added in-app help tooltips throughout the settings pages - hover the question mark icons for setup guides.Update to v1.7.2 and try re-adding your playlist. For the renamed episodes, you may want to manually delete the orphan .info.json files from that Season 2016 folder since they were created before the fix.Let me know how the rest of your testing goes!Just saw suggestions portion:Shorts filter - The current filter already catches any video under 60 seconds in length, regardless of whether it was posted as a YouTube Short or as a regular video. So if a channel posts a 45-second video on their main page, it will still be detected and skipped (if shorts filtering is enabled for that channel).That said, I can see how some channels post slightly longer "short content" (trailers, teasers, 90-second clips) that you'd also want to filter out. I'm looking into adding a configurable minimum duration setting per channel so you can set your own threshold (e.g. skip anything under 3 minutes). That would give more control than the fixed 60-second cutoff.Channel percentages - Agreed, skipped episodes shouldn't count against the completion percentage. Adding this to the list.Subtitles/captions - Great idea. yt-dlp already supports downloading subtitles and auto-generated captions, just needs a toggle in the settings to enable it. On the list for a future update. Edited April 10Apr 10 by sworcery
April 10Apr 10 Author v1.7.10 UpdateBig update with Sonarr-style episode management and several new features:Monitored/Unmonitored episodes - Toggle monitoring per episode or in bulk. Download All only queues monitored videos.Status icons - Colored icons showing download state at a glance (downloaded, missing, queued, failed, skipped, etc.)Collapsible seasons - Videos grouped by year with per-season Download Missing and Monitor buttonsQuality cutoff - Set minimum quality per channel and search for upgrades on existing downloadsPer-episode actions - Three-dot menu with Re-download, Rename File, Delete File, and SkipSubtitle download - Toggle in Settings to download captions with videosMin duration filter - Per-channel setting to skip videos below a configurable lengthPlaylist support fix - Playlists now properly index all videosCompletion percentages - Skipped/unmonitored videos no longer count against channel progressIn-app help links - "Learn more" links throughout settings that go directly to the relevant documentationUpdate to v1.7.10 to get everything!
April 10Apr 10 Loving these updates! This is WELL on the way to being the best YT tool on Unraid! A few bugs to report - would you like these here or as issues in your github for tracking? I can do either/both. ================================================Re-added channels fail to sync: When a channel is deleted, then re-added, it fails to sync with an 'internal server error'.Docker logline:INFO: 192.168.1.159:54180 - "GET /api/v1/settings/ HTTP/1.1" 500 Internal Server ErrorTested with multiple channels with identical behavior. ========================The github reported settings bug seems to be affecting me as well. I will run the commands listed in that issue and respond there in case that OP doesn't. ========================In regards to deleting channels, could the delete button once clicked then offer to delete the channel in the app and leave the files, or to wipe the entire folder and files as well?========================Lastly, I'm running into an old perms issue I used to face with the arr stack apps where I don't have perms to modify downloaded files. With the arr apps there's a perms step that can be set (see attached) that would perfectly resolve this issue. My thought is it would sit nicely next to the file name setting, maybe making that 'file management' settings instead. Not to be presumptuous. I have to say, I'm wildly impressed with your development turn around time! That's 4 pushes in a single day addressing nearly every major issue! All that minecraft modding paid off! Edited April 10Apr 10 by alicecantsleep
April 11Apr 11 Author @alicecantsleep - For bug tracking, GitHub issues work best - I can link fixes directly to releases. The forum is great for feature requests and discussion though.All the issues you reported have been addressed in v1.7.11:Re-added channels failing to sync - fixedSettings not persisting - fixedChannel delete options (keep files vs delete everything) - addedFile permissions (chmod/chown like Sonarr) - addedUpdate your container and let me know how it goes!
April 11Apr 11 I seem to have a channel stuck with the re-add sync bug. The re-added channel bug itself is definitely fixed as I've tested with 3 channels and 2 work fine. So I think I just have the one stuck in my system somehow. Any troubleshooting suggestions?
April 11Apr 11 Author @alicecantsleep This should be fixed in v1.7.13 (just released). There's a new Force Re-scan button on the channel detail page under the Monitoring section, next to "Scan Now." It will wipe all the video records for that channel and re-scan from scratch, which should clear out whatever is stuck.Update to v1.7.13 and give that a try on the stuck channel. Let me know if it sorts it out!
April 11Apr 11 16 minutes ago, sworcery said:@alicecantsleep This should be fixed in v1.7.13 (just released). There's a new Force Re-scan button on the channel detail page under the Monitoring section, next to "Scan Now." It will wipe all the video records for that channel and re-scan from scratch, which should clear out whatever is stuck.Update to v1.7.13 and give that a try on the stuck channel. Let me know if it sorts it out!Checking the logs in v1.7.13 and I can see it's properly fetching the items (7), but I see 'internal service error' and the channel says 0/0 videos. Strange. Unfortunately playlist additions result in the same error: ======18:30:35 [ERROR] app.services.ytdlp_service: Failed to get channel info for https://www.youtube.com/playlist?list=PLadHblBH0KNRd_GIdkfcbUVzXOquXzKAE: ERROR: [youtube:tab] PLadHblBH0KNRd_GIdkfcbUVzXOquXzKAE: YouTube said: The playlist does not exist.=======Re-scan Error Logs:18:33:07 [INFO] apscheduler.executors.default: Job "Process download queue (trigger: interval[0:00:30], next run at: 2026-04-11 13:33:37 CDT)" executed successfully18:33:14 [INFO] app.services.channel_service: Scanning channel: SPLIFF RADIOショー18:33:15 [INFO] httpx: HTTP Request: GET https://www.googleapis.com/youtube/v3/channels?part=contentDetails&id=UCv6FU8CavXsGuKZX7kimcjg&key=AIzaSyBq3OfM2xURab1eqFzaTaqCjYXh-9IvddY "HTTP/1.1 200 OK"18:33:15 [INFO] httpx: HTTP Request: GET https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2CcontentDetails&playlistId=UUv6FU8CavXsGuKZX7kimcjg&maxResults=50&key=AIzaSyBq3OfM2xURab1eqFzaTaqCjYXh-9IvddY "HTTP/1.1 200 OK"18:33:15 [INFO] app.services.youtube_api_service: YouTube API found 7 videos for channel UCv6FU8CavXsGuKZX7kimcjg18:33:15 [INFO] app.services.channel_service: Video list returned 7 entries for SPLIFF RADIOショー (url: https://www.youtube.com/channel/UCv6FU8CavXsGuKZX7kimcjg)18:33:15 [INFO] httpx: HTTP Request: GET https://www.youtube.com/feeds/videos.xml?channel_id=UCv6FU8CavXsGuKZX7kimcjg "HTTP/1.1 200 OK"18:33:15 [INFO] app.services.ytdlp_service: RSS feed returned dates for 7 videos from channel UCv6FU8CavXsGuKZX7kimcjg18:33:18 [INFO] app.services.channel_service: Scanning channel: SPLIFF RADIOショー18:33:18 [INFO] httpx: HTTP Request: GET https://www.googleapis.com/youtube/v3/channels?part=contentDetails&id=UCv6FU8CavXsGuKZX7kimcjg&key=AIzaSyBq3OfM2xURab1eqFzaTaqCjYXh-9IvddY "HTTP/1.1 200 OK"18:33:18 [INFO] httpx: HTTP Request: GET https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2CcontentDetails&playlistId=UUv6FU8CavXsGuKZX7kimcjg&maxResults=50&key=AIzaSyBq3OfM2xURab1eqFzaTaqCjYXh-9IvddY "HTTP/1.1 200 OK"18:33:18 [INFO] app.services.youtube_api_service: YouTube API found 7 videos for channel UCv6FU8CavXsGuKZX7kimcjg18:33:18 [INFO] app.services.channel_service: Video list returned 7 entries for SPLIFF RADIOショー (url: https://www.youtube.com/channel/UCv6FU8CavXsGuKZX7kimcjg)18:33:18 [INFO] httpx: HTTP Request: GET https://www.youtube.com/feeds/videos.xml?channel_id=UCv6FU8CavXsGuKZX7kimcjg "HTTP/1.1 200 OK"18:33:18 [INFO] app.services.ytdlp_service: RSS feed returned dates for 7 videos from channel UCv6FU8CavXsGuKZX7kimcjg18:33:23 [INFO] httpx: HTTP Request: GET http://127.0.0.1:4416/ping "HTTP/1.1 200 OK"18:33:37 [INFO] apscheduler.executors.default: Running job "Process download queue (trigger: interval[0:00:30], next run at: 2026-04-11 13:34:07 CDT)" (scheduled at 2026-04-11 13:33:37.002207-05:00)18:33:37 [INFO] apscheduler.executors.default: Running job "Watch cookies.txt for external updates (trigger: interval[0:01:00], next run at: 2026-04-11 13:34:37 CDT)" (scheduled at 2026-04-11 13:33:37.004157-05:00)18:33:37 [INFO] apscheduler.executors.default: Job "Watch cookies.txt for external updates (trigger: interval[0:01:00], next run at: 2026-04-11 13:34:37 CDT)" executed successfully18:33:37 [INFO] apscheduler.executors.default: Job "Process download queue (trigger: interval[0:00:30], next run at: 2026-04-11 13:34:07 CDT)" executed successfully
April 11Apr 11 Author @alicecantsleep Two things going on here:SPLIFF RADIO showing 0/0 with "internal service error": Your logs show the channel getting scanned twice within 4 seconds (manual scan + scheduled scan colliding). The second scan tried to insert the same 7 videos and crashed on a duplicate key constraint, which rolled back the whole thing. Fixed in v1.7.14 -- concurrent scans on the same channel are now prevented.Update to v1.7.14 and either use the Force Re-scan button (next to Scan Now) to clear out the stuck state and start fresh, or just hit Scan Now -- it should work cleanly now that the race condition is fixed.Playlist addition failing: The error "YouTube said: The playlist does not exist" is coming from YouTube itself rejecting that playlist ID. That specific playlist may be private, deleted, or the URL might have extra characters. Can you double-check the playlist URL works when you open it in a browser? If it does, share the URL format you're using (with the list ID redacted if you prefer) and I'll take a look.
April 11Apr 11 v1.7.14Oh gosh, duh, the playlist needs to be public. That one's on me! Not sure why this channel is refusing to show the 7 videos it's indexed. I've tried both scan types, as well as removing and re-adding the channel. It's a stubborn one! I notice when I run force re-scan it says 'Cleared 0 old records, found 0 videos on rescan' so maybe it's not clearing the database properly. stuckchannellogs.txt Edited April 11Apr 11 by alicecantsleep Added detail.
April 11Apr 11 Author @alicecantsleep Found it -- this is the same orphan record issue from before the foreign key fix. When the channel was originally deleted, the 7 video records were left behind in the database. Since video IDs are globally unique, re-adding the channel sees those orphan records and thinks the videos already exist, so it skips all of them.Fixed in v1.7.15 (just pushed). Update and delete/re-add the channel one more time -- the orphan records will be cleaned up automatically on startup, and the scan should pick up all 7 videos.
April 11Apr 11 41 minutes ago, sworcery said:@alicecantsleep Found it -- this is the same orphan record issue from before the foreign key fix. When the channel was originally deleted, the 7 video records were left behind in the database. Since video IDs are globally unique, re-adding the channel sees those orphan records and thinks the videos already exist, so it skips all of them.Fixed in v1.7.15 (just pushed). Update and delete/re-add the channel one more time -- the orphan records will be cleaned up automatically on startup, and the scan should pick up all 7 videos.Seems to have broken my docker with the following error in logs:sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: download_logs[SQL: DELETE FROM download_logs WHERE video_id IN (SELECT id FROM videos WHERE channel_id NOT IN (SELECT id FROM channels))](Background on this error at: https://sqlalche.me/e/20/e3q8)Database initialization failed
April 11Apr 11 Author That's my fault -- the orphan cleanup I added in v1.7.15 had a typo in a table name. Fixed in v1.7.16, just pushed. Update and it should start right up. Sorry about that!
April 21Apr 21 An option to limit scrape by year of certain channels would be nice.The concurrent downloads needs some love, it seems the download delays are counted from when one starts downloading - not independently. Is this intended?The result of that is that you only see more of concurrent downloads when you are scrapping larger videos.*if cookies are not premium, it seem to only download at 480p while there is better quality available. Edited April 22Apr 22 by CyklonDX
April 25Apr 25 Author @CyklonDX You were right, this was a bug. The download delay timer was a single shared timer, so concurrent downloads were all stepping on each other instead of staggering independently. Fixed now. If you have 3 concurrent slots and a 15 second delay, downloads will kick off at T+0, T+15, and T+30 regardless of how long each one takes. The queue also fills all available slots at once now instead of picking up one at a time.Limit Scrape by Year Done! Each channel now has a "Download From Year" field in the Download Settings section. Set it to something like 2023 and it'll only grab videos from 2023 onward. Anything older gets skipped during scans. Leave it blank to download everything like before.480p Without Premium CookiesThis one is actually a YouTube restriction, not something on our end. Without cookies from a Premium account, YouTube throttles the available streams, and for some content you'll only get 480p even though higher quality exists on the page. If you want full quality access, make sure your cookies are coming from a browser that's logged into YouTube Premium. You can check if your cookies are working under Settings > Authentication.
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.