In September 2026, the self-hosted NewsBlur installation was unable to refresh YouTube RSS feeds.
A typical feed URL looked like:
https://www.youtube.com/feeds/videos.xml?channel_id=UCtoaZpBnrd0lhycxYJ4MNOQ
The feed itself was valid.
Opening the same URL directly in a web browser successfully returned YouTube's RSS/Atom XML.
However, NewsBlur's feed history repeatedly reported:
YouTube fetch failed (404)
This affected many unrelated YouTube channels, establishing that the problem was not an invalid channel ID or a bad RSS export.
NewsBlur does not treat every youtube.com feed URL as an ordinary RSS feed.
Its code contains a special YouTube fetcher:
utils/youtube_fetcher.py
NewsBlur detects URLs hosted by youtube.com using:
is_youtube_feed_address()
The regular feed fetcher then routes matching URLs through:
YoutubeFetcher
instead of downloading the RSS/Atom URL directly.
The important code path was located in:
utils/feed_fetcher.py
and originally contained:
if is_youtube_feed_address(address):
The dedicated YouTube fetcher subsequently uses the YouTube Data API.
The local self-hosted installation contained a placeholder YouTube API key:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
As a result, NewsBlur's special YouTube handling failed even though YouTube's public RSS endpoint itself worked normally.
NewsBlur's:
is_youtube_feed_address()
function is used in several places besides the initial feed download.
In particular, NewsBlur uses YouTube detection later for push/PubSub handling.
Therefore, changing the function globally to say that:
/feeds/videos.xml
is not a YouTube feed could have disabled useful YouTube-specific behavior elsewhere.
Instead, the fix was limited specifically to the decision that invokes NewsBlur's API-based YouTube fetcher.
The following file was modified:
~/docker/newsblur/utils/feed_fetcher.py
Inside the containers, the same file appears as:
/srv/newsblur/utils/feed_fetcher.py
The original line was:
if is_youtube_feed_address(address):
It was changed to:
if is_youtube_feed_address(address) and "/feeds/videos.xml" not in address:
This means:
* ordinary YouTube URLs can still use NewsBlur's special YouTube handling;
* official youtube.com/feeds/videos.xml URLs bypass the API-specific fetcher;
* the official feed is instead downloaded and parsed through NewsBlur's normal RSS/Atom mechanism;
* other NewsBlur YouTube detection remains intact.
Before modifying the file, a backup was made.
The working patch command was:
docker exec newsblur_web sh -c 'cp /srv/newsblur/utils/feed_fetcher.py /srv/newsblur/utils/feed_fetcher.py.bak && sed -i '"'"'0,/if is_youtube_feed_address(address):/s//if is_youtube_feed_address(address) and "\/feeds\/videos.xml" not in address:/'"'"' /srv/newsblur/utils/feed_fetcher.py'
Verify the change with:
grep -n 'is_youtube_feed_address(address)' ~/docker/newsblur/utils/feed_fetcher.py
Expected result:
344: if is_youtube_feed_address(address) and "/feeds/videos.xml" not in address:
The newsblur_web container has the following bind mount:
/home/mike/docker/newsblur -> /srv/newsblur
Therefore:
/srv/newsblur/utils/feed_fetcher.py
inside the container is the same underlying host file as:
/home/mike/docker/newsblur/utils/feed_fetcher.py
The change therefore survives ordinary:
* container restarts;
* docker compose down / up;
* container recreation.
It is not merely stored in the writable layer of one Docker container.
After changing the Python code, restart the web application:
docker restart newsblur_web
NewsBlur's Celery worker also uses the same source tree and performs background/scheduled feed fetching.
Restart it as well:
docker restart newsblur_celery
This ensures both processes reload the modified Python code.
A known failing YouTube feed was manually refreshed in NewsBlur.
Before the change, its fetch history showed:
YouTube fetch failed (404)
After the change, the same official YouTube RSS URL fetched successfully.
The test feed used during troubleshooting was the HasanAbi / Hasan Piker YouTube feed.
Once the test succeeded, no individual changes were required for the remaining YouTube subscriptions.
Existing feeds using URLs of the form:
https://www.youtube.com/feeds/videos.xml?channel_id=...
can remain unchanged.
NewsBlur will process them normally as its background scheduler reaches each feed.
Because the NewsBlur directory is a Git working tree, the modification can be viewed with:
cd ~/docker/newsblur git diff -- utils/feed_fetcher.py
The expected diff is:
- if is_youtube_feed_address(address): + if is_youtube_feed_address(address) and "/feeds/videos.xml" not in address:
This provides an easy way to verify that the local patch is still present.
The patch is persistent across Docker container recreation because the NewsBlur source is bind-mounted from the host.
However, it is still a local modification to the NewsBlur Git source tree.
A future:
git pull
may:
* preserve the modification; * refuse to update because of the local change; * produce a merge conflict; * or require the local patch to be reapplied.
Before updating NewsBlur, check:
cd ~/docker/newsblur git status git diff -- utils/feed_fetcher.py
Do not blindly discard the local modification unless NewsBlur's upstream code has fixed the underlying problem.
This workaround should ideally be temporary.
If a future NewsBlur release fixes self-hosted YouTube RSS handling, the local modification can be removed and the upstream version tested again.
Before removing it:
* Check NewsBlur's recent changes/issues for a YouTube RSS or YouTube API fix.
* Save the current local diff.
* Restore the upstream version of the relevant logic.
* Restart both newsblur_web and newsblur_celery.
* Manually refresh a known YouTube feed.
* Confirm that the feed succeeds without the local workaround.
If the upstream implementation still produces:
YouTube fetch failed (404)
restore/reapply the local modification.
The RSS URLs exported from the previous RSS reader were not the problem.
YouTube's public RSS endpoint continued to work.
The failure occurred because NewsBlur intercepted official YouTube RSS URLs and routed them through its YouTube Data API implementation.
The local fix simply tells NewsBlur:
If the URL is already an official /feeds/videos.xml feed, fetch it as an ordinary feed instead of converting it through the YouTube API.
Return to: