Downloading YouTube videos is a total rigamarole.

Begin with a Google search for "download youtube", try the first link, dead end, try the second link, click here to check YoutTube URL, wait for conversion, look at this advertisement, please install MacKeeper, download this .dmg, you must install java... blahblahblah.

The 80's Movie Hacker way is far superior. Once it's set up, there's no muss, no fuss... and it's so straightforward that even a novice can do it. Consider this command to download only the audio from a specific YouTube link:

$ ytdl -a https://www.youtube.com/watch?v=Cne5-46K99s

Yes my friends… it's that simple.

Disclaimer: being an 80's hacker involves dipping into the command line—a place where many computer users fear to tread. We'll also be using some scripts written in Python. What does that mean? Don't worry, let's press on.

If you feel intimidated, remember: in 15 minutes you'll feel like a super geek (in a good way).


Introduction to the Terminal

Our journey begins by opening Terminal which is located in Applications > Utilities

It should look something like this:

What do those words mean? Let's highlight the different components:

  • green is the user's name
  • yellow is the computer's name
  • blue is the terminal's current working directory, which is by default the user's home directory (represented by "~")
  • magenta dollar sign means we can issue a command
  • that grey block represents your cursor's current position for entering text

Note, every time I write a $ before a snippet of code, it's a command for Terminal. For example:

$ sample-command

Should be copied and pasted into your Terminal as:


With that in mind, let's issue a command before we install anything, just to get the hang of it. Type the following into the terminal:

$ ls

Hit enter any time you see a command prefixed with a $.

[like now]


Oooh! Some words showed up. Those are all the folders and files in your current directory (which, remember, is " ~ ").

Installing pip, a Python Package Manager

pip is a very handy package manager for Python. It's like a helper that takes care of the tedious or complicated aspects of installing things—for instance, the tools we need to download YouTube videos.

pip will streamline the install process of:

  • pafy – (short for Python API for YouTube), which includes
    • ytdl – (short for YouTube Download), our YouTube downloader

Now, is pip is named after the character from Great Expectations?


Therefore, I suggest you read all subsequent pip commmands in a cheerful British accent.

Any time you issue a command to pip, it looks something like this. Use that power wisely.

Any time you issue a command to pip, it looks something like this. Use that power wisely.


In order to use pip, first we have to download its installer file. We can accomplish this with:

$ curl -O https://bootstrap.pypa.io/get-pip.py

What does that command mean?

In a nutshell, it calls a built-in command called 'curl' to save a file (-O) located at a specific URL (https://bootstrap.pypa.io/get-pip.py).

When run, it should look like this:


Okay some words appeared, how can we double-check that "get-pip.py" actually downloaded?

Let's look at all the files and folders again with ls (which means list everything in the current directory):

$ ls

Hey! " get-pip.py " has been downloaded!

(I've highlighed it for effect, if yours is also yellow… please consult a doctor..)


That's cool, now we have a setup script. But how do we use it to install pip? Pretty simply:

$ sudo python get-pip.py

Let's quickly break this down:

  • sudo = substitute user do… it simply means do a command with more authority. Like this.
  • python = use python to run whatever comes next
  • get-pip.py = the file we want to run with python

Great. So we paste that command in, hit enter, and… uh-oh.

Terminal has stopped and asked us for our password because we're issuing a sudo command.

Don't be worried when nothing appears as you type your password; just enter it like normal and hit enter.

This will run the installer, and give us a screen similar to this:


Now having run the installer script, let's try:

$ pip

pip will respond with instructions on how to use it—and with about as much brevity as Dickens himself.

I didn't ask for your life story, pip!

I didn't ask for your life story, pip!

Installing pafy, Python API for YouTube

Our new friend pip can connect to the internet and get packages we want. The one for YouTube downloading is part of a larger package called pafy, so let's get it:

$ sudo pip install pafy

You shouldn't need to enter your password again, since you're using sudo for the second time in one session.


And now pafy has been installed—thanks pip, cheerio!

Working with ytdl, a Component of pafy


Try typing this into the terminal:

$ ytdl

Chances are the response is something like:

/usr/bin/python3: bad interpreter: No such file or directory

(if you didn't get this error, skip the next step)


Shucks. What's the deal?

Well since OS X doesn't come with Python 3, we have two choices:

  1. Install Python3
  2. Tell ytdl to use the default python on our Mac

Choice #2 is far simpler—despite looking more complicated at first blush. Hold onto your butts.

$ sudo nano /usr/local/bin/ytdl

Huh? Breakdown:

  • sudo = we've seen this one before. It gives us super powers.
  • nano = a text editor. We need to edit the ytdl file to change a line of text.
  • /usr/local/bin/ytdl = the location of the file we want to edit with nano.

After we issue that command, our work is simple. This is what our terminal should look like:


Look at that first line that reads:


That's our culprit! It's telling ytdl to use Python3… which we don't have. To correct this, we just need to delete the "3" and save the changes.

We can use the right arrow key on the keyboard to move our cursor to after the 3. Like this:


Now we press delete and it should read:


Awesome. Press Ctrl+X to exit, and nano will prompt you to save. Like this:


Type a "y" without the quotes and press enter. Now you'll be asked what to call this file:


We don't want to change the filename, so let's just hit enter and nano should disappear.

Hooray! We just edited where ytdl looks for python—now it should work properly.

How can we check? Let's test it by calling ytdl again:

$ ytdl

It worked!

Ignore the word error; now we can start using ytdl to do our download bidding.


Let's start with a Youtube video. Its URL is https://www.youtube.com/watch?v=Fr-lpDHRED4

Downloading Video

Firstly, we can download the best possible version of the video with

$ ytdl -b https://www.youtube.com/watch?v=Fr-lpDHRED4
N.B.  ytdl also accepts the video's ID as an argument for downloading. This is the part after "watch?v=" in any YouTube link.


ytdl also accepts the video's ID as an argument for downloading. This is the part after "watch?v=" in any YouTube link.


But this is a song… so we don't want the video part.

Downloading Audio

Let's change "-b" to "-a" to fetch the best possible audio stream.

As well, let's shorten the URL to just the video ID located after the "=" sign. https://www.youtube.com/watch?v=Fr-lpDHRED4

$ ytdl -a Fr-lpDHRED4

Now we're cooking with gas.

Getting Information

What if we forget which video "Fr-lpDHRED4" is?

How can we check out its information before downloading it?

With "-i" of course. Let's try:

$ ytdl -i Fr-lpDHRED4

which has the following output:


Displaying/Downloading Available Streams

Every YouTube link actually contains multiple videos; YouTube chooses which one to show based on our connection speed so that we can begin watching as quickly as possible.

So consider the following: What if we want to download a low-resolution version of a particular video using ytdl?

First we need to see which streams are available, before choosing which one to download. This is accomplished by calling ytdl without any options.

$ ytdl Fr-lpDHRED4

Which gives the result:


So this YouTube video has 11 available streams for us to download, neat. We could save a low quality one like number 6 on the list by telling ytdl to download number 6:

$ ytdl -n 6 Fr-lpDHRED4

That's handy!


Download Location

ytdl will download your video or audio to the Terminal's current working directory.

You can change the directory with the change directory command

$ cd <location>

Where <location> is replaced by a file path. For instance, if you want to download to your desktop

$ cd ~/Desktop

Try ytdl now and you'll see the download appear on your desktop.

Note when you quit Terminal, it will default to your home folder when re-opened—also known as " ~ " without the quotes.

Downloading a List

What if we want to download a bunch of videos without manually running the command each time? Simple.

Consider the following text file, let's call it links.txt:


Cool, it has six lines… each containing one link to one song.

So how do we download them with one command instead of six?

One way is with a command like:

$ <links.txt xargs -I{} ytdl -a {}

Which looks complicated... what does it do?

  • < links.txt = pass the information held in this file to…
  • xargs = a handy command that will
  • -I{} = look at each individual line of the file and put it in a placeholder that occurs later As an aside: -I{} implies the option -L 1 and therefore execute as many times as there are lines in the input file.
  • ytdl = our YouTube downloader
  • -a = an option for ytdl, telling it to get audio
  • {} = the aforementioned placeholder; every line of links.txt will be inserted where this second set of curly braces occur.

And of course if we wanted each link downloaded as a video instead of audio, we could simply change the -a to -b.

$ <links.txt xargs -I{} ytdl -b {}

iTunes Troubleshooting

Many audio files downloaded with ytdl won't work right out of the box with iTunes; a quick fix is to change their extension from ".mp4" to "m4a".

iTunes will now play them properly, but will display an incorrect total duration for each track. We can check Google for solutions later.

As well, sometimes a YouTube URL contains ".ogg" audio files… these will need to be converted, and Google knows how.

Final Thoughts

This is just scratching the surface.

We haven't even gotten into the power of ytdl's parent pafy. We could write a python script to communicate with YouTube's API to get data like:

  • how many videos does a user have?
  • how many views per video?
  • average # of views for all uploaded videos?
  • top ten videos by rating?

Then we could call our ol' pal ytdl to work with that data.

For instance, if we know how many videos a user has uploaded and the url for each one, then we could download every. single. one of them.