TL;DR: No supported JavaScript runtime could be found is a warning, not a failure: yt-dlp keeps going, but it skips the step that unlocks some formats. Run pip install -U "yt-dlp[default]" and install Deno, or add --js-runtimes node if you already have Node. In our test of 8 videos, the format you lose every time without a runtime is 18, the classic 360p file with audio and video together. If you only want the words from a video, you may not need any of this: subtitles downloaded fine with no runtime, and TranscriptFetch's YouTube Transcript API skips yt-dlp altogether.
We ran everything below on 2026-11-07 with yt-dlp 2026.10.26, from a home connection, on Linux. Results from a cloud server can differ, and we say below where that matters.
What the warning says
This is the full text:
WARNING: [youtube] No supported JavaScript runtime could be found. Only deno is enabled by default; to use another runtime add --js-runtimes RUNTIME[:PATH] to your command/config. YouTube extraction without a JS runtime has been deprecated, and some formats may be missing. See https://github.com/yt-dlp/yt-dlp/wiki/EJS for details on installing oneYouTube makes clients solve small JavaScript challenges before it hands over some formats. yt-dlp needs a JavaScript runtime to run them. The part people miss is "Only deno is enabled by default". You can have Node installed, and yt-dlp will still print this, because it won't use Node unless you ask.
What you actually lose
We listed formats for 8 videos, once with no runtime and once with Node and the solver script, and compared the format IDs.
| Video | Formats, no runtime | Formats, with runtime | Only with the runtime |
|---|---|---|---|
dQw4w9WgXcQ | 44 | 45 | 18 |
jNQXAC9IVRw | 24 | 25 | 18 |
9bZkp7q19f0 | 44 | 41 | 18 |
kJQP7kiw5Fk | 40 | 41 | 18 |
M7lc1UVf-VE | 38 | 39 | 18 |
aqz-KE-bpKQ | 49 | 57 | 18, 136, 247, 256, 258, 328, 380, 773 |
HCZNs3AyFM8 | 49 | 50 | 18 |
tCMl1AWfhQQ | 44 | 45 | 18 |
Format 18 was missing on all 8. It is the 360p MP4 with audio and video in one file, so it's the format that works without ffmpeg. If your script asks for -f 18, it now depends on a runtime.
Beyond that, the loss was small on this sample. On dQw4w9WgXcQ with no runtime, format 140 (audio) and format 137 (1080p video) both downloaded in full. One video, aqz-KE-bpKQ, lost seven more formats. Another, 9bZkp7q19f0, went the other way: the run with no runtime listed four formats (271, 313, 400, 401) that the run with Node didn't. We ran each setup once per video, and YouTube's answers can vary between requests, so treat that as noise until proven otherwise.
That is today's picture. yt-dlp calls running without a runtime deprecated, so don't count on it staying this mild.
The fix, tested five ways
We tested each setup on dQw4w9WgXcQ:
| Setup | Warnings | Formats listed |
|---|---|---|
pip install yt-dlp, no runtime | No supported JavaScript runtime | 48 |
pip install yt-dlp, --js-runtimes node | Solver script skipped, plus n challenge and signature solving failed | 48 |
Same, plus --remote-components ejs:github | None | 49 |
pip install "yt-dlp[default]", --js-runtimes node | None | 49 |
pip install "yt-dlp[default]", Deno on the PATH | None | 49 |
The counts here include storyboards, which is why they run higher than the table above.
The second row is the trap. You add a runtime, and the warning is replaced by two scarier ones. A runtime alone isn't enough: yt-dlp also needs the solver script, which is a separate package called yt-dlp-ejs. A plain pip install yt-dlp doesn't bring it in. The [default] extra does.
If you have Node already
python3 -m pip install -U "yt-dlp[default]"
yt-dlp --js-runtimes node "URL"To stop typing the flag, put it in your config file. We ran this with a config file holding the one line below, and the warning went away.
mkdir -p ~/.config/yt-dlp
echo '--js-runtimes node' >> ~/.config/yt-dlp/configIf you would rather use Deno
Deno is the only runtime yt-dlp enables by default, so once it is on your PATH there is no flag to add. Their installer is the usual route:
curl -fsSL https://deno.land/install.sh | sh
python3 -m pip install -U "yt-dlp[default]"
yt-dlp "URL"We got our Deno binary with pip install deno (2.9.8) rather than that script, and yt-dlp printed Solving JS challenges using deno with no warnings.
yt-dlp also supports QuickJS and Bun through --js-runtimes. We didn't test those.
If you can't install the solver package
If you installed yt-dlp from a distro package, or you have a runtime but no yt-dlp-ejs, let yt-dlp fetch the script itself:
yt-dlp --js-runtimes node --remote-components ejs:github "URL"In our run that downloaded yt.solver.lib.min.js from the yt-dlp/ejs releases on GitHub (0.8.0), and the warnings cleared. This runs code fetched at run time, so you may prefer the pip package on a production machine. yt-dlp's help says this flag isn't needed with the official executable, or with the right version of yt-dlp-ejs installed.
If you call yt-dlp from Python
The same setting is an option on YoutubeDL. This ran for us and listed 49 formats, format 18 included:
import yt_dlp
opts = {"skip_download": True, "js_runtimes": {"node": {}}}
with yt_dlp.YoutubeDL(opts) as ydl:
info = ydl.extract_info("dQw4w9WgXcQ", download=False)
print(len(info["formats"]))If you only need the text
With no runtime at all, this still wrote the English subtitle file, with the warning printed above it:
yt-dlp --skip-download --write-auto-subs --sub-langs en --sub-format "json3/vtt" "URL"So if subtitles are all you're after, the warning isn't your problem. Our guide to yt-dlp subtitles to plain text covers the cleanup, because the automatic files repeat lines.
A runtime also won't get you past a block. Sign in to confirm you're not a bot is a separate problem about your IP address, and it's common on cloud servers. We covered that in the bot check guide. We didn't run today's tests from a server, so we can't say how the format counts look from one.
If you're fetching text from a server and don't want to maintain yt-dlp, a runtime, a solver script and proxies, TranscriptFetch is the hosted route, and it's ours. You send a video ID or URL to the YouTube Transcript API and get the transcript back as JSON. You start with 50 free credits, which don't renew, and failed requests aren't charged.
curl https://transcriptfetch.com/api/v2/transcripts/video \
-H "Authorization: Bearer $TRANSCRIPTFETCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"video":"dQw4w9WgXcQ"}'It won't help if you need the video file itself. For that, yt-dlp with a runtime is the right tool.
FAQ
A warning. In our tests yt-dlp carried on and downloaded audio, 1080p video and subtitles. yt-dlp says running without a runtime is deprecated and some formats may be missing, and format 18 was missing on all 8 videos we tried.
Only Deno is enabled by default. Node, QuickJS and Bun have to be switched on with --js-runtimes, for example --js-runtimes node. You can put that line in your yt-dlp config file so you don't have to type it.
In our test it came from having a runtime but no solver script. Installing with pip install -U "yt-dlp[default]" brought in yt-dlp-ejs and cleared it. Adding --remote-components ejs:github, which downloads the script from GitHub, also cleared it.
Not in our test. With no runtime, yt-dlp still wrote the English subtitle file, with the warning printed. On a server the bot check can still stop you, because that is a separate block.
