Is there a utility that can search YouTube from the command line, and then either view or download the search results according to user input?

$ youtube-search madonna

1 Madonna - Hung Up (Official Music Video)
madonna ♩ 180M views 9 years ago
"Hung Up" by Madonna from Confessions On A Dance Floor, available now.

2 Madonna - Like A Prayer (Official Music Video)
madonna ♩ 69M views 9 years ago
2006 WMG Like A Prayer.


And then you can enter:

  • "v1" to view video 1 (with VLC, etc.)
  • "d1-3" to download videos 1-3 (with youtube-dl, etc.)
  • "n" to view next page of search results

What I tried so far:

googler works partially with YouTube, but for some reason only shows two search results when searching for "Madonna". Also there is not the choice between view and download.

youtube-dl has a search function, but doesn't seem to print the search results nor accept user input. youtube-dl -j ytsearch:madonna lists metadata about search results, but doesn't seem to contain the video link, title and description that would be desired.

  • Take a look at github.com/mps-youtube/mps-youtube. You can do all three things you mentioned with it.
    – ritiek
    Jan 23, 2019 at 15:22
  • 1
    @ritiek: I heard about it, but refrained from installing it due to the insane number of dependencies: libpng, frei0r, glib, pixman, cairo, graphite2, icu4c, harfbuzz, libvpx, opencore-amr, opus, sdl2, snappy, theora, x264, x265, ffmpeg, libtiff, little-cms2, [email protected], mujs, openjpeg, webp, leptonica, tesseract, zimg, vapoursynth and mpv. Maybe it's a great utility, but seems like way overkill for my needs.
    – forthrin
    Jan 23, 2019 at 20:15
  • So... the answer to your question is, "yes", but your response is, "I don't want to install that." Jan 23, 2019 at 21:16

4 Answers 4


Firstly, you need ytsearchN: to ask for N results. Secondly, make sure that you have the latest youtube-dl (I had some issues with an old version).

The following basic script will get 5 results, display their titles and urls, and ask which to download. Making it respond to the commands "vN" and "dN" would be simple ("dN" is effectively already implemented); I'm not sure how you could get the next page of results, though.



youtube-dl -j "ytsearch5:$*" > $tempfile

# workaround for lack of mapfile in bash < 4
# https://stackoverflow.com/a/41475317/6598435
while IFS= read -r line
done < <(cat $tempfile | jq '.webpage_url' | tr -d '"' )
# # for bash >= 4
# mapfile -t youtube_urls < <(cat $tempfile | jq '.webpage_url' | tr -d '"' )

cat $tempfile | jq '.fulltitle, .webpage_url'

while :
    echo "Enter video number to download."
    read i
    # don't download anything if you just press enter
    if [ ! x"$i" == x"" ]
        # to make numbering of videos more intuitive (start from 1 not 0)
        youtube-dl --no-progress ${youtube_urls[$i - 1]} &

You might, perhaps, want to redirect the output from youtube-dl to a file (or /dev/null), though it could also be considered useful.

  • A very lightweight and nice suggestion. However, macOS Unix doesn't have mapfile and jq. jq seems available in Homebrew, but how do I get mapfile? Or can your script be rewritten for compatibility? stackoverflow.com/questions/41475261/…
    – forthrin
    Jan 23, 2019 at 20:21
  • 1
    mapfile is a built-in (like help, while, alias etc.), in bash ≥ 4; by default macOS ships with lower versions of bash, as they're allergic to GPLv3 (the version they ship is the last that was under GPLv2). You can install the latest bash with homebrew. I'll modify the script to avoid use of mapfile, but bash 4 has many great features (among other things "bracketed paste" and nicer customisation of keybindings) so it might be worth installing anyway.
    – aplaice
    Jan 23, 2019 at 20:53
  • I tried installing Homebrew bash (5.0.0), but there's no mapfile there. Thanks for the modification! I'll try it out. Also, I think many people will benefit from this script.
    – forthrin
    Jan 23, 2019 at 21:37
  • After upgrading bash (follow steps: itnext.io/upgrading-bash-on-macos-7138bd1066ba), installing jq (brew install jq) and changing #!/usr/local/bin/bash in the beginning of the script, it worked! Thanks May 17, 2020 at 15:44

A selenium based solution:

#!/usr/bin/env python

from pyvirtualdisplay import Display
from selenium import webdriver
import time
import argparse
import re
import subprocess

class bcolors:
    BLUE = '\033[94m'
    GREEN = '\033[92m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'


parser = argparse.ArgumentParser()
parser.add_argument("query", help="enter the youtube search query here")
args = parser.parse_args()

display = Display(visible=0, size=(800, 600))

driver = webdriver.Chrome()  # Optional argument, if not specified will search path.
search_box = driver.find_element_by_name('search_query')

page = driver.find_elements_by_css_selector("ytd-video-renderer.ytd-item-section-renderer")
for video in page:
    a3=video.find_elements_by_css_selector('yt-formatted-string[has-link-only_]:not([force-default-style]) a.yt-simple-endpoint.yt-formatted-string')[0].text
    a4=video.find_elements_by_css_selector('#metadata-line.ytd-video-meta-block span.ytd-video-meta-block')[0].text
    a5=video.find_elements_by_css_selector('#metadata-line.ytd-video-meta-block span.ytd-video-meta-block')[1].text
    print i,a2
    print a3+"    "+a4+"    "+a5
    print a1
    print a6


print bcolors.BOLD+bcolors.GREEN+"Available options- v: open video in VLC media player, d: download video by number, q: quit"+bcolors.ENDC
print bcolors.BOLD+bcolors.BLUE+"Usage - option:number    or    option:beginning-end"+bcolors.ENDC
while entry!="q":
    if pattern1.match(entry):
        bashCommand="vlc "+link_list[int(link)]
    elif pattern2.match(entry):
        bashCommand="youtube-dl "+" ".join(link_list[b:e])
    print bashCommand
    process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
    output, error = process.communicate()

I haven't tried running the actual commands (Popen) but I think this should do it.

  • 1
    Nice try, however I think it would be better to use a lightweight HTML scraper such as BeautifulSoup. Not everyone has Chrome installed.
    – forthrin
    Jan 23, 2019 at 20:17
  • The same thing can be done for firefox also right? And I have never used BeautifulSoup, so probably I will look into that, thanks Jan 23, 2019 at 23:08

Not quite pure CLI but why not use yad or zenity to ease the selection process?

Register as a developer and get an API key for youtube then this works 'as is'.

If you don't want to use the API then uncomment and comment the lines as noted and it will use 'youtube-dl' instead, though the search is slower.



function down { youtube-dl  "$DOWNURL$1"; }
function watch { xdg-open "$DOWNURL$1"; }

SEARCH=$( yad --center --title="Search for clip" --text="Enter search term" --entry 2>/dev/null)
SEARCH=$(echo $SEARCH | sed 's/ /%20/g')

#uncomment the 2 lines below to use youtube-dl 
#youtube-dl -j "ytsearch$NORESULTS:$SEARCH" | jq '.id, .title' > yt.search
#SELECTION=$(cat yt.search | sed 's/^\"\"$/\"No entry\"/' | sed 's/&/+/g' | sed '/^[^ ]*$/ i \"FALSE\"' | yad --center --checklist --list --width=1000 --height=800 --column=Check --column=ID --column=Title --button='gtk-cancel':0 --button='Download':2 --button='watch':4)

#comment out the following 3 lines if using youtube-dl
curl -i -G -d "$QUERY" "$APIURL" |  sed '1,15d' | jq '.items[] | .id.videoId, .snippet.title, .snippet.description' > yt.search
SELECTION=$(cat yt.search | sed 's/^\"\"$/\"No entry\"/' | sed 's/&/+/g' | sed '/^[^ ]*$/ i \"FALSE\"' | yad --center --checklist --list --width=1000 --height=800 --column=Check --column=ID --column=Title --column=Description --button='gtk-cancel':0 --button='Download':2 --button='watch':4)

case $ACTION in
        echo "cancelled"
        for i in $(echo $SELECTION | sed 's/|/\n/g' | grep -P "^\"[^ ]*\"$" | sed 's/\"//g'); do 
            if [ $ACTION -eq "2" ]; then #the download button was pressed 
                down "$i"
            else #the watch button was pressed
                watch "$i"
  • It's good you let the user choose not to use the API, so downloads can be done anonymously. What's yad? I'm on macOS Unix. Can it be replaced with something more generic?
    – forthrin
    Jan 23, 2019 at 20:23
  • yad is a tool for generating gui for scripts, another is zenity. According to apple.stackexchange there is a utility called cocoadialogfor macOS.
    – bu5hman
    Jan 24, 2019 at 2:57
  • How many seconds does ytsearch10 take on your machine? Here it takes 20 seconds, which makes it unusable.
    – forthrin
    Jan 27, 2019 at 17:08
  • ytsearch takes forever for me too. That's why I had a look at the API. It's like lightning compared to ytsearch.
    – bu5hman
    Jan 27, 2019 at 17:13

Here is a terminal-based tool: ytfzf. Found about it here.

Testing it in 2022 K/ubuntu I find it less buggy and less complicated than mps-youtube.

Type ytfzf in terminal to start. See ytfzf -h for options like audio only and download.

The search is done after the variable is set, so for example

  • in order to get only audio: ytfzf -m <search_term>
  • in order to download video: ytfzf -d <search_term>

We can add that into a application launcher with a line like Exec=konsole -e ytfzf -m, called "Youtube audio..." - and similarly for other options.

enter image description here

enter image description here

enter image description here

Scroll up-down and press Enter or double-click to select title.

enter image description here

Default player is mpv, download is done by curl, settings are in ~/.config/ytfzf/conf.sh.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .