YouTube channel RSS feed returns 404 for a channel that exists
The short answer
On 2026-10-12 YouTube's channel RSS feed (feeds/videos.xml) answered 404 Not Found, and sometimes 500, for channels that plainly existed. It lasted about 8 hours and then fixed itself. My research bot read each 404 as "this channel is gone", skipped it, and quietly collected about half the usual videos.
The fix is on my side. I now count any non-200 answer as a failure, retry only the failed channels after a pause, and fail the run loudly when too many feeds stay unread. If the daily video count suddenly halves, the feed is the first thing I check.
What the feed answered
GET https://www.youtube.com/feeds/videos.xml?channel_id=UC… → 404 Not Found
GET https://www.youtube.com/feeds/videos.xml?channel_id=UC… → 500
(the same channel switched between 404 and 500 from one request to the next)
Channels that had videos: 30 · answered 200: 1
YouTube's own official channel feed: 404 Not FoundWhere I hit it
- What reads the feeds
- A research bot (Python, standard library only) that collects yesterday's videos from YouTube channel RSS feeds
- Feed URL
- https://www.youtube.com/feeds/videos.xml?channel_id=UC…
- When
- 2026-10-12, from about 08:15 to 16:09 (about 8 hours)
- Channels that morning
- 30 channels that had videos; 1 answered 200
- Second machine
- A second server reading 15 channels: all 15 answered 404
Why it happens
My collector treated a 404 as "channel deleted" and moved on. A deleted channel has no feed, so that looked reasonable. That morning, though, the 404s came from channels that were posting normally. The report had about half the videos it usually has, and the failure count showed only 53, because the skipped channels were never counted as failures.
The channel ids and my network were probably fine (this part is inference). Of 30 channels that had videos, 1 got a 200. The same channel flipped between 404 and 500 from one request to the next, YouTube's own official channel feed returned 404 too, and a second server reading 15 channels got 404 for all 15. That points to the feed endpoint on YouTube's side. I couldn't find any explanation from YouTube.
Other people have hit the same thing. A Google developer forum thread collects reports of 404s on this endpoint for active channels, including February 2026. A GitHub issue from October 2026 describes a scheduled job failing on the same 404, once on a 500. Feeder's help page on YouTube feeds says the feed server sometimes answers every feed with 404 for hours at a time.
The fix
- Treat every non-200 answer as a failure. A 404 from this endpoint does not prove the channel is gone, so return nothing and let the caller count it.
import http.client import urllib.request FEED = "https://www.youtube.com/feeds/videos.xml?channel_id={}" def fetch(channel_id): """Feed XML, or None if the request failed for any reason. A 404 here is a failure to retry, not proof that the channel was deleted.""" try: with urllib.request.urlopen(FEED.format(channel_id), timeout=20) as r: return r.read() except (OSError, http.client.HTTPException): # HTTPError (404, 500 ...), timeouts, cut-off reads return None - Keep the failed channel ids and fetch only those again after a pause. I wait 30 seconds, then 2 minutes, then 5 minutes. Channels that still fail are reported as failed, never dropped.
import time RETRY_WAITS = (30, 120, 300) # seconds def scan(channel_ids): feeds, todo = {}, list(channel_ids) for wait in (0, *RETRY_WAITS): if not todo: break time.sleep(wait) failed = [] for cid in todo: xml = fetch(cid) if xml is None: failed.append(cid) else: feeds[cid] = xml todo = failed return feeds, todo # todo now holds the channels that never answered - Fail the run when too many feeds are still unread. If more than 20% fail, my collector ends the run as failed and its timer tries again 8 minutes later, up to 4 times in 2 hours. After the cutoff (08:25 for the 08:15 run) it publishes what it has, with a partial-report warning at the top, because the feed can stay down for hours and waiting could mean no report at all.
MAX_FAIL_SHARE = 0.2 # more than 20% unread = a bad run feeds, failed = scan(channel_ids) if len(failed) > MAX_FAIL_SHARE * len(channel_ids): if before_cutoff(): raise RuntimeError(f"{len(failed)}/{len(channel_ids)} channel feeds failed") # the timer runs it again report.warning = f"Partial report: {len(failed)} channel feeds could not be read" - Watch the daily total as well. Half the usual count was the only visible sign that day, so a sudden halving should send you to the feed before anything else. My collector relies on the failed-share check above; this one line is the extra check I'd add to any feed reader.
if today_count < usual_count / 2: alert(f"Only {today_count} videos today (usual: {usual_count}). Check the YouTube feeds first.")
How I checked it worked
- The feeds came back on their own at 16:09, about 8 hours after the first failures that morning. Nothing on my side changed.
- The collector's offline tests cover the fix: a 404 counts as a failure, only failed channels are fetched again, and a run where most feeds fail either errors out (before the cutoff) or produces a report marked partial.
- When any channel feed fails, the morning report now says how many, so a bad feed day shows up in the report instead of as a quietly shorter list.