So you just logged in to a server, and all you have is a command line. How do you download a file here?

With a command called curl which can download a file pretty much anywhere: On a Linux server, a Windows server (or home computer), even on a BSD server, or a MacOS computer.

The Syntax of the cURL Command

cURL, the so-called "client for URLs," is an extremely flexible command-line program. You can change its behavior with command-line options (also called flags).

The general syntax of a curl command is:

curl [options] [URL]

For example, in a command like this:

curl -L -O "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"

-L and -O are two separate command-line options / flags. This is also a good example of how you can use multiple options in the same command.

💡
Important: Options are case-sensitive. An uppercase -O does NOT do the same thing as a lowercase -o.

After the options, you pass the URL. In this case: https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip.

💡
It's a good habit to wrap the URL between " " double quotes. This prevents the shell from misinterpreting it. Certain symbols like ; & ? ( ) $ * have special meanings in command interpreters. Without quotes, if the URL contains one of those characters, the shell might try to execute something entirely different from what you expected.

So, in a curl command, write the URL part as "https://example.com/data.zip" instead of https://example.com/data.zip

Now let's see how you can download files with cURL.

Download Files with cURL

The easiest way to download a file with cURL is to run this command:

curl -O "URL"

Example of a real command:

curl -O "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"

-O is the option that tells cURL to automatically name the downloaded file, according to the name it gets from the URL. For example, for the URL above:

https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip

The file will be named:

bbb_sunflower_1080p_60fps_normal.mp4.zip

-O is required. Without -O, cURL would try to display the content from that URL, instead of saving it into a file. So make sure you remember to add -O.

As you download a file with that command, you'll see the progress, along with other data, like:

  • Total size of the file to be downloaded.
  • How much has been received up to this point.
  • Download speed (look at current speed to see the current transfer rate / how many MB, or GB per second).
  • And you'll also see total time spent on this download, along with the estimated time left until the download finishes.

All in all, useful information. But if you think this output is too messy, you have an alternative.

Show a Progress Bar for cURL Downloads

If you don't care about the current speed, and all that information, you can just tell cURL to show you a simple progress bar. To do that, just add an extra option to the previous command: -#.

So instead of curl -O "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip", you run:

curl -# -O "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"

And now you'll see progress displayed like this:

With a bar that fills up all the way to 100%.

Manually Choose a Name for the File Downloaded with cURL

-O (uppercase -O) will work fine, for most downloads. It will automatically name the downloaded file, according to the URL source. But, in some edge-case scenarios, it can lead to weird names for the downloaded files.

If a URL ends with a name like download?id=514 then your downloaded file might get the same name, download?id=514.

If uppercase -O is not working for your scenario, you can use lowercase -o instead. With lowercase-o you manually choose a name for the downloaded file.

For example, to name your downloaded file mydownload.zip, you would run a command like this:

curl -o mydownload.zip "URL"

Example of a real command:

curl -o mydownload.zip "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"

But what if you want to download a very large file?

Fix an Interrupted Download (Resume Download with cURL)

If you ever downloaded huge files, you already know: The bigger the file, the bigger the risk for that download to get interrupted. And then you have to restart from zero, losing all of your progress.

Fortunately, cURL can fix this issue. Already downloaded 10GB out of 12GB total? And then the download got interrupted? You can keep your progress and restart the download to get just the remaining 2GB.

To make cURL resume an interrupted download (continue where it left off), add -C - to your options. That's "minus C," followed by a space, then another minus.

curl -C - [rest of your options] [URL]

-C - is a weird one, because it's made out of two parts:

  1. -C is the option that tells cURL to continue at.
  2. And then it expects you to tell it where to continue from (a number).

So it would expect something like -C 500. Which would make it skip the first 499 bytes, and continue downloading from byte 500, onward.

Since you don't want to manually specify what byte to continue from, -C - is a smart way to tell cURL:

Figure out where this download was interrupted, and continue from there.

Think of that second -, after -C, as meaning "there."

Examples of real commands:

# Resume download (-C -), and automatically name the download file (-O)

curl -C - -O "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"


# Resume download (-C -), show progress bar (-#), and automatically name the download file (-O)

curl -C - -# -O "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"


# Resume download (-C -), show progress (-#), and name the downloaded file mydownload.zip (-o mydownload.zip)

curl -C - -# -o mydownload.zip "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"

Nothing Was Downloaded? Make cURL Follow Redirects

Sometimes, you'll notice that you run a command like:

curl -O "https://tinyurl.com/5x3dsm56"

And the download seems to finish instantly. Even more, if you look at the file that was downloaded:

You'll see it's actually an HTML file, instead of a ZIP file, video, or whatever you tried to download.

This usually happens because of a redirect. Essentially, the URL you passed to cURL redirects to a secondary URL. And the content you actually need is hosted at that secondary URL. But cURL tries to download from the first one.

You can tell cURL to follow redirects, so that it ends up where the content actually is.

To make cURL follow redirects, add the -L option to your option list:

curl -L [rest of your options] [URL]

Example of a real command:

curl -L -O "https://tinyurl.com/5x3dsm56"

Just keep in mind that if you use uppercase -O (to name the download file automatically), you might end up with a weird filename. Like 5x3dsm56, in this case. But you can use the lowercase -o option, to manually choose a filename (as described in a previous section).

So, to use redirects, but also name your file mydownload.zip:

curl -L -o mydownload.zip "https://tinyurl.com/5x3dsm56"

If you also want to show a simple progress bar, and resume an interrupted download, just add the -#, and -C - options explained in the previous sections:

curl -# -C - -L -o mydownload.zip "https://tinyurl.com/5x3dsm56"

This is an example of how you can chain many more options in a curl command.

User, and Password Authentication with cURL

You can configure Apache, Nginx, and other web servers, to ask for a username and password, before allowing visits to certain pages.

So this is not about web pages that ask you for a user and password in the page itself (in forms from that web page).

It's about the web server itself, asking for those details. The kind you fill in, in a popup dialog box like this:

If you are trying to download something from a password-protected web page, you can tell cURL to authenticate to that web server, with a user and password, by adding the -u option:

curl -u "user:password" [rest_of_options] [URL]

Note how, again, you wrap this between " " double quotes. As was recommended for the URL, in an earlier section.

That's because the password might contain special characters, which the command interpreter could process in unexpected ways. With the double quotes, you avoid that potential unexpected behavior.

Example of a real command:

curl -u "alex:notaverygoodpassw0rd!" -O "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"

If you're on a shared server, know that other (logged in) members can see that password. Which might, or might not be an issue. They can look at active processes, and see the password.

You can avoid that by simply telling cURL to ask for the password interactively. To do that, after -u just specify the username, but NOT the password.

Instead of:

curl -u "alex:notaverygoodpassw0rd!" -O "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"

Run:

curl -u alex -O "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"

And cURL will now ask for the password, like this:

Note that nothing will be displayed as you type here. That's normal (to hide the password from anyone watching your screen).

Suppress cURL Output (Useful in Scripts)

When you use cURL on the command line, it's useful that it shows you output like this:

But there are scenarios where you might not need that output. For example, in scripts that should run automatically.

You can tell cURL to be silent (don't show output), with the -s option.

So in a command like this:

curl -o mydownload.zip "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"

Just add -s in front of your other options:

curl -s -o mydownload.zip "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_60fps_normal.mp4.zip"

And now cURL won't display anything while it's downloading content:

Know that this also suppresses errors from the output. So cURL won't tell you if anything goes wrong. For example, if you try to download a file from a non-existent website:

curl -s -o mydownload.zip "https://abcdefgh.kodekloud.com/file.zip"

No error from cURL, since all output messages are silenced with -s.

In a script, it might not be a problem, since you usually deal with these potential issues internally. With if statements which get status codes from curl, and then do what is required: Output messages to the user, trigger certain follow-up actions, and so on.

However, if you want cURL to be silent, but also show errors (when they occur), you can use -sS. The first lowercase -s tells cURL to be silent, but the second, uppercase S tells cURL to show errors.

In a nutshell, cURL will normally be silent, but it will display a message if it encounters critical errors.

curl -sS -o mydownload.zip "https://abcdefgh.kodekloud.com/file.zip"

Note how, this time, the curl command tells you it encountered an error:

To wrap it all up, here's a summary (and reminder) of useful cURL commands.

Cheatsheet for cURL Command

Task Command
Download, and automatically name file curl -O "URL"
Manually choose a name (like "file.zip") for downloaded file curl -o file.zip "URL"
Resume interrupted download (for automatically named file) curl -C - -O "URL"
Resume interrupted download for a file named "file.zip" curl -C - -o file.zip "URL"
Follow redirects curl -L -O "URL"
Auth with user and password curl -u "user:password" -O "URL"
Quiet mode / No text output or errors curl -s -O "URL"
Quiet mode / No text output, but show errors curl -sS -O "URL"
Show a progress bar curl -# -O "URL"

Learn More

We hope you found this tutorial useful. And if you want to learn more about system administration, check out this learning path:

System Administrator Learning Path | Kodekloud
Explore our System Administrator learning path. Discover the skills and certifications for effective systems management.

See you in the next blog!