Use Cases

Published 2026-05-27Updated 2026-07-15

Check if a YouTube Video Has Uploaded Subtitles

Use yt-dlp to distinguish between uploaded subtitles and auto-generated captions on YouTube videos, and quickly determine subtitle status via jq, grep, or custom commands.

Using yt-dlp, you can distinguish between the following two types of subtitles:

  • Uploaded subtitles: Located in the subtitles field, usually provided by the author, channel, or content provider.

  • Auto-generated captions: Located in the automatic_captions field, generated by YouTube's automatic speech recognition or auto-translation.

Note: The presence of uploaded subtitles does not necessarily mean they were manually created by the author.

For example, subtitles for some news videos might come from the program's built-in Closed Captions.

Test Videos

Plain text
Has uploaded subtitles:
https://www.youtube.com/watch?v=7ARBJQn6QkM
 
No uploaded subtitles:
https://www.youtube.com/watch?v=SS5uEinPunc

Viewing the Subtitle List

Bash
yt-dlp \
  --js-runtimes node \
  --list-subs \
  "https://www.youtube.com/watch?v=7ARBJQn6QkM"

--list-subs will output separately:

Plain text
Available automatic captions for ...

and:

Plain text
Available subtitles for ...

The former refers to auto-generated captions, and the latter refers to uploaded subtitles.

When the output shows:

Plain text
[info] Available subtitles for 7ARBJQn6QkM:
Language Name    Formats
en       English vtt, srt, ttml, srv3, srv2, srv1, json3

It indicates that the video has uploaded subtitles with the language code en.

When the output shows:

Plain text
SS5uEinPunc has no subtitles

It indicates that the video does not have uploaded subtitles.

This does not mean the video definitely has no auto-generated captions; for automatic captions, you need to check the Available automatic captions section.

JavaScript Runtime

Parameter:

Bash
--js-runtimes node

This allows yt-dlp to use Node.js to execute YouTube's JavaScript challenge solver.

Before using this parameter, ensure that a compatible version of Node.js is installed on your system:

Bash
node --version

You can also use other JavaScript runtimes supported by yt-dlp. For example, if Bun is installed, you can use:

Bash
--js-runtimes bun

In some cases, not specifying --js-runtimes still allows you to fetch video information, but there might be missing formats or features, so it is not recommended as a long-term configuration.

Using jq for Determination

--list-subs might output a large number of auto-generated and auto-translated captions. When you need to make determinations in a script, it is recommended to read the JSON output from yt-dlp instead of parsing terminal logs.

Installing jq

macOS:

Bash
brew install jq

Determining if Uploaded Subtitles Exist

Bash
yt-dlp \
  --js-runtimes node \
  --skip-download \
  --dump-single-json \
  "https://www.youtube.com/watch?v=7ARBJQn6QkM" \
| jq -r '
  if ((.subtitles // {}) | length) > 0 then
    "Has uploaded subtitles: " + ((.subtitles | keys) | join(", "))
  else
    "No uploaded subtitles"
  end
'

Possible output:

Plain text
Has uploaded subtitles: en

This reads from:

Plain text
subtitles

Instead of:

Plain text
automatic_captions

Therefore, it will not mistakenly identify YouTube's auto-generated or auto-translated captions as uploaded subtitles.

Using grep for Determination

When doing a quick check in the Shell, you can also match the output of --list-subs:

Bash
output=$(
  yt-dlp \
    --js-runtimes node \
    --list-subs \
    "https://www.youtube.com/watch?v=7ARBJQn6QkM" \
    2>&1
)
 
if echo "$output" | grep -q "Available subtitles for"; then
  echo "Has uploaded subtitles"
else
  echo "No uploaded subtitles"
fi

This method relies on yt-dlp's terminal output text, making it suitable for quick checks but not recommended as the core determination logic for a long-term workflow.

For long-term use, you should prioritize parsing the subtitles field returned by --dump-single-json.

Creating a Custom Command

You can encapsulate the determination logic into a globally available Shell command.

Creating the Script

Create the file:

Plain text
~/MyFiles/bin/has-youtube-subs

With the following content:

Bash
#!/usr/bin/env bash
 
set -euo pipefail
 
if [[ $# -ne 1 ]]; then
  echo "Usage: has-youtube-subs <YouTube URL>" >&2
  exit 1
fi
 
yt-dlp \
  --js-runtimes node \
  --skip-download \
  --dump-single-json \
  "$1" \
| jq -r '
  if ((.subtitles // {}) | length) > 0 then
    "Has uploaded subtitles: " + ((.subtitles | keys) | join(", "))
  else
    "No uploaded subtitles"
  end
'

Adding Execute Permission

Bash
chmod +x ~/MyFiles/bin/has-youtube-subs

Adding the Script Directory to PATH

Open:

Bash
vim ~/.zshrc

Add:

Bash
export PATH="$HOME/MyFiles/bin:$PATH"

Apply the configuration immediately:

Bash
source ~/.zshrc

Executing the Command

Bash
has-youtube-subs \
  "https://www.youtube.com/watch?v=7ARBJQn6QkM"

Output:

Plain text
Has uploaded subtitles: en

Once this command is added to your PATH, it can be executed from any directory.

Determining on the YouTube Website

Open the video player and click in order:

Plain text
Settings (gear icon)
→ Subtitles/CC

Appearing:

Plain text
English

Usually indicates that this track is not a YouTube auto-generated caption.

Appearing:

Plain text
English (auto-generated)

Explicitly indicates that this caption was generated by YouTube's automatic speech recognition system.

Please note:

Plain text
English

Only indicates that it is not a subtitle track labeled as auto-generated; you cannot conclusively determine based on this that the subtitles were manually created by the video author.