Correct cURL

    Published on

    Let’s say that you’re writing a shell script or that you’re working on some CI process and you need to download a file from the internet. Should be easy right? Just type curl '{url}' > {output-file} and you’re done. That’s not quite correct. While it may work, it’ll come bite you in the ass later. Here’s how you can call cURL to download a file without it blowing up in the future:

    curl --fail --location --silent --show-error --output '{output-file}' '{url}'
    

    You’ll need to replace {url} with the url of the file you want to download and {output-file} with the name of the file you want to write to. Keep the quotes, they’re important.

    If all you want is a snippet to copy / paste, feel free to take this line and roll with it. If you want to learn what’s up with all those flags and why they’re here, keep reading.

    --fail

    When cURL encounters an HTTP error it doesn’t fail by default. By not failing, I mean that it exits with an exit code of 0. This means that your script, CI process or whatever else calling cURL won’t stop or report a failure if you get an HTTP error.

    Also, cURL will output the error message directly into your output file. This means that you may get an error down the line because some other step gets confused by the file you just downloaded being an error message instead of what it should be. You’ll end up with a really confusing error instead of the clear HTTP error you could have gotten earlier.

    Passing the --fail flag solves this issue. It tells cURL to stop and to exit with a non-zero exit code when it encounters an HTTP error code. This is what allows your script, CI, etc. to recognize that there was a failure. It also prevents cURL from writing the error message to the output file.

    Sadly this flag is not perfect. Some authentication errors may slip through such as 401 and 407 HTTP codes.

    --location

    By default cURL will not follow HTTP redirects. This means that if the file behind that url ever changes and there’s a redirect put in place, cURL won’t follow it.

    To remediate that, you can use the --location flag which will tell cURL to follow redirects.

    If you’re wondering where the name comes from, it’s named after the Location HTTP header. This header holds the location where the url is being redirected to.

    --silent and --show-error

    The --silent flag supresses cURL’s normal output. This hides certain messages and the progress bar. There’s one catch with --silent. It suprresses too much output. If something goes wrong, like a 404 error, it’ll supress that output as well. This is where the --show-error flag comes in. It’ll ensure that cURL still shows you error messages when it fails.

    In the context of a script or CI process it’s often a good idea to stop the progress bar since that can be quite noisy. Also some CI systems can’t handle cURL’s progress bar which uses special terminal commands to rewrite its own output.

    If you want the progress bar, you can ommit these flags.

    --output <file>

    Normally cURL outputs the body of the HTTP response to stdout. You can redirect that output to a file > or to another program using |. This is fine when everything goes right. It can become a problem when things go wrong. Since stdout is being redirected the error body and any errors or warnings from cURL may be redirected as well.

    When you use the --output <file> option, cURL will write the response body to the given file. If something goes wrong in the process, stdout is still available for use.

    On top of that, when you use --output <file>, cURL is able to show a progress bar for the download. This is helpful in cases where you have omitted the --silent flag.

    While, it’s possible to use stream redirection with cURL and not experience any problems. I find that using --output <file> is more reliable.

    Why the long flags?

    I made a point to use the long form of all flags. I encourage you to do so as well. This is because the long flags are fairly self evident. You can probably understand what they do just by looking at them.

    The short version of all the flags is -sSfLo. While this is definetely shorter and may even make you feel clever, it makes sure that anyone who may be reading your script, CI, etc. and who is not familiar with cURL’s flags will be lost. They’ll either have to look them up or just blindly trust that they’re right and there for a good reason.

    By using the long flags, you’re trading in horizontal screen space which is quite abundant in our modern world for clarity and readability. That’s a good trade in my book.