Back to blog

yt-dlp "No supported JavaScript runtime could be found": what you lose and how to fix it

We ran yt-dlp with no runtime and with Node across 8 videos, then tried five setups. What the warning costs you, and the install that clears it.

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.

Guide

What the warning says

This is the full text:

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 one

YouTube 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.

Guide

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.

VideoFormats, no runtimeFormats, with runtimeOnly with the runtime
dQw4w9WgXcQ444518
jNQXAC9IVRw242518
9bZkp7q19f0444118
kJQP7kiw5Fk404118
M7lc1UVf-VE383918
aqz-KE-bpKQ495718, 136, 247, 256, 258, 328, 380, 773
HCZNs3AyFM8495018
tCMl1AWfhQQ444518

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.

Guide

The fix, tested five ways

We tested each setup on dQw4w9WgXcQ:

SetupWarningsFormats listed
pip install yt-dlp, no runtimeNo supported JavaScript runtime48
pip install yt-dlp, --js-runtimes nodeSolver script skipped, plus n challenge and signature solving failed48
Same, plus --remote-components ejs:githubNone49
pip install "yt-dlp[default]", --js-runtimes nodeNone49
pip install "yt-dlp[default]", Deno on the PATHNone49

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.

Guide

If you have Node already

bash
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.

bash
mkdir -p ~/.config/yt-dlp
echo '--js-runtimes node' >> ~/.config/yt-dlp/config
Guide

If 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:

bash
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.

Getting started

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:

bash
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.

Guide

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:

python
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"]))
Guide

If you only need the text

With no runtime at all, this still wrote the English subtitle file, with the warning printed above it:

bash
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.

bash
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.