- fail2ban-digest-mode-fleet: recidive-only email model, sshd now silent, defaults-debian.conf gotcha added - netdata-docker-health-alarm-tuning: 30m/10m config, tuning history table - New: wp-fail2ban-logpath-debian-ubuntu, lora-adapter-gguf-conversion-fails, tailscale-status-json-hostname-localhost-ios - Various article updates and nav index refreshes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7.3 KiB
| title | domain | category | tags | status | created | updated | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| yt-dlp YouTube JS Challenge Fix (Fedora) | troubleshooting | general |
|
published | 2026-04-02 | 2026-04-30T05:21 |
yt-dlp YouTube JS Challenge Fix (Fedora)
Problem
When running yt-dlp on Fedora, downloads may fail with the following warnings and errors:
WARNING: [youtube] No supported JavaScript runtime could be found.
WARNING: [youtube] [jsc:deno] Challenge solver lib script version 0.3.2 is not supported (supported version: 0.4.0)
WARNING: [youtube] 0qhgPKRzlvs: n challenge solving failed: Some formats may be missing.
ERROR: Did not get any data blocks
ERROR: fragment 1 not found, unable to continue
This causes subtitle downloads (and sometimes video formats) to fail silently, with the MP4 completing but subtitles being skipped.
Root Causes
- No JavaScript runtime installed — yt-dlp requires Deno or Node.js to solve YouTube's JS challenges
- Outdated yt-dlp — the bundled challenge solver script is behind the required version
- Remote challenge solver not enabled — the updated solver script must be explicitly fetched
Fix
1. Install Deno
Deno is not in the Fedora repos. Install via the official installer:
curl -fsSL https://deno.land/install.sh | sh
sudo mv ~/.deno/bin/deno /usr/local/bin/deno
deno --version
Alternatively, Node.js works and is available via
sudo dnf install nodejs.
2. Update yt-dlp
sudo pip install -U yt-dlp --break-system-packages
If installed via standalone binary:
yt-dlp -U
3. Enable Remote Challenge Solver
Add --remote-components ejs:github to the yt-dlp command. This fetches the latest JS challenge solver from GitHub at runtime:
yt-dlp -f 'bestvideo[vcodec^=avc]+bestaudio[ext=m4a]/bestvideo+bestaudio' \
--merge-output-format mp4 \
-o "/plex/plex/%(title)s.%(ext)s" \
--write-auto-subs --embed-subs \
--remote-components ejs:github \
https://www.youtube.com/watch?v=VIDEO_ID
4. Persist the Config
Create a yt-dlp config file so --remote-components is applied automatically:
mkdir -p ~/.config/yt-dlp
echo '--remote-components ejs:github' > ~/.config/yt-dlp/config
Maintenance
YouTube pushes extractor changes frequently. Keep yt-dlp current:
sudo pip install -U yt-dlp --break-system-packages
Known Limitations
n-Challenge Failure: "found 0 n function possibilities"
Even with Deno installed, the remote solver downloaded, and yt-dlp up to date, some YouTube player versions can still fail n-challenge solving:
WARNING: [youtube] [jsc] Error solving n challenge request using "deno" provider:
Error running deno process (returncode: 1): error: Uncaught (in promise)
"found 0 n function possibilities".
WARNING: [youtube] n challenge solving failed: Some formats may be missing.
ERROR: [youtube] Requested format is not available.
This is a known upstream issue tied to specific YouTube player builds (e.g. e42f4bf8). It is not fixable locally — it requires a yt-dlp patch when YouTube rotates the player.
Workaround: Use a permissive format fallback instead of forcing AVC:
yt-dlp -f 'bestvideo+bestaudio/best' \
--merge-output-format mp4 \
-o "/plex/plex/%(title)s.%(ext)s" \
--write-auto-subs --embed-subs \
--remote-components ejs:github \
https://www.youtube.com/watch?v=VIDEO_ID
This lets yt-dlp pick the best available format rather than failing on a missing AVC stream. To inspect what formats are actually available:
yt-dlp --list-formats --remote-components ejs:github \
https://www.youtube.com/watch?v=VIDEO_ID
HTTP 429 Too Many Requests + Impersonation Warning
Downloads or subtitle fetches fail with:
WARNING: The extractor specified to use impersonation for this download,
but no impersonate target is available.
ERROR: Unable to download video subtitles for 'en-en-US': HTTP Error 429: Too Many Requests
Cause: yt-dlp needs curl_cffi to impersonate a real browser's TLS fingerprint. Without it, YouTube detects the non-browser client and rate-limits with 429s. Subtitle downloads are usually the first to fail (YouTube's timedtext endpoint has its own, stricter per-IP bucket).
Fix (pin curl_cffi to the supported range):
pip3 install --user -U "curl_cffi>=0.10,<0.15" "yt-dlp-ejs>=0.8"
⚠️ Do not run a bare
pip install -U curl_cffi. As of yt-dlp 2026.03.17, the backend inyt_dlp/networking/_curlcffi.pyhard-caps at0.14.x:ImportError: Only curl_cffi versions 0.5.10 and 0.10.x through 0.14.x are supportedInstalling
curl_cffi 0.15.0silently disables impersonation —yt-dlp --list-impersonate-targetswill show every source as(unavailable)even thoughimport curl_cffiworks fine. Always pin to<0.15until yt-dlp widens the range.
Verify:
yt-dlp --list-impersonate-targets | head -5
Should show real entries (Chrome-133 Macos-15 curl_cffi), not the (unavailable) table.
If the 429 persists on subtitles only: the timedtext bucket is already hot from prior retries. Either wait 15–60 min, skip subs for this download (--no-write-subs --no-write-auto-subs), or throttle with --sleep-subtitles 5 on retry. The video/audio path is not affected.
Companion gotcha — yt-dlp-ejs version drift: if yt-dlp -U reports yt-dlp is current but you still see:
WARNING: Challenge solver lib script version 0.3.2 is not supported ... supported version: 0.8.0
…then the EJS solver helper is stale. yt-dlp -U does not update it. Upgrade explicitly:
pip3 install --user -U yt-dlp-ejs
SABR-Only Streaming Warning
Some videos may show:
WARNING: [youtube] Some android_vr client https formats have been skipped as they
are missing a URL. YouTube may have enabled the SABR-only streaming experiment.
This is a YouTube-side experiment. yt-dlp falls back to other clients automatically — no action needed.
pip Version Check
pip show does not accept --break-system-packages. Run separately:
yt-dlp --version
pip show yt-dlp
Format Not Available: Strict AVC+M4A Selector
The format selector bestvideo[vcodec^=avc]+bestaudio[ext=m4a] will hard-fail if YouTube doesn't serve H.264 (AVC) video for a given video:
ERROR: [youtube] Requested format is not available. Use --list-formats for a list of available formats
This is separate from the n-challenge issue — the format simply doesn't exist for that video (common with newer uploads that are VP9/AV1-only).
Fix 1 — Relax the selector to mp4 container without enforcing codec:
yt-dlp -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/bestvideo+bestaudio' \
--merge-output-format mp4 \
-o "/plex/plex/%(title)s.%(ext)s" \
--write-auto-subs --embed-subs \
https://youtu.be/VIDEO_ID
Fix 2 — Let yt-dlp pick best and re-encode to H.264 via ffmpeg (Plex-safe, slower):
yt-dlp -f 'bestvideo+bestaudio' \
--merge-output-format mp4 \
--recode-video mp4 \
-o "/plex/plex/%(title)s.%(ext)s" \
--write-auto-subs --embed-subs \
https://youtu.be/VIDEO_ID
Use --recode-video mp4 when Plex direct play is required and the source stream may be VP9/AV1. Requires ffmpeg.
Inspect available formats first:
yt-dlp --list-formats https://youtu.be/VIDEO_ID