How to Download Files with curl

curl is one of the most versatile command-line tools for downloading files over HTTP, HTTPS, FTP, and dozens of other protocols. Whether you need to save a single API response to a file or automate batch downloads in a shell script, curl has a flag for it. This guide covers every download-related option — from basic file saving with -o and -O to resuming interrupted transfers with -C -, throttling bandwidth with --limit-rate, and showing progress bars. Each flag includes a clear explanation, common usage patterns, and a ready-to-copy example.

Download Flags Quick Reference

-o

Write output to a named file instead of stdout

-O

Write output to a file named like the remote file

-L

Follow HTTP 3xx redirects automatically

-C -

Continue/resume a previous file transfer

--limit-rate

Limit the transfer speed to the given rate

--max-filesize

Refuse to download files larger than the specified size

-J

Use the Content-Disposition header to name the file

-#

Display transfer progress as a simple progress bar

-u

Provide username:password for server authentication

--retry

Retry the transfer on transient errors (number of times)

--retry-delay

Wait this many seconds between retries

-T

Upload a local file to a URL (PUT by default)

--create-dirs

Create local directories as needed when saving output

-s

Suppress progress meter and error messages

--output-dir

Save output file(s) in the specified directory (curl 7.73+)

curl -o: Save to a Specific Filename

What it does
The -o (or --output) flag tells curl to save the response body to a file you specify. Without it, curl prints the response to stdout (your terminal). You can use any filename and path — curl will create the file or overwrite an existing one.
Common usage
Use -o when you need to control the exact filename or save to a specific directory. It works with any protocol — HTTP, HTTPS, FTP, SFTP, and more. Combine with -L to handle redirects and -s for silent operation in scripts.
$ curl -o report.pdf https://example.com/files/report.pdf

curl -O: Save with the Remote Filename

What it does
The -O (or --remote-name) flag saves the downloaded file using the filename extracted from the URL. For example, if the URL ends with /data.csv, curl creates a file called data.csv in the current directory.
Common usage
Use -O when the remote filename is meaningful and you don't need to rename it. You can pass multiple -O flags to download several files in one command. Note: if the URL doesn't contain a filename (e.g., ends with /), curl will fail — use -o instead.
$ curl -O https://example.com/files/data.csv

curl -L: Follow Redirects

What it does
The -L (or --location) flag makes curl automatically follow HTTP redirects — 301 (Moved Permanently), 302 (Found), 307, and 308. Without -L, curl returns the redirect response itself instead of the actual content.
Common usage
Most download URLs redirect at least once (e.g., from HTTP to HTTPS, or from a short URL to the actual file). Always combine -L with -o or -O when downloading files. By default curl follows up to 50 redirects; change this with --max-redirs.
$ curl -L -o latest.tar.gz https://github.com/user/repo/releases/latest/download/app.tar.gz

curl -C -: Resume Interrupted Downloads

What it does
The -C - (or --continue-at -) flag tells curl to automatically detect the size of the existing partial file and resume the download from where it left off. The server must support the HTTP Range header for this to work.
Common usage
If a large download was interrupted by a network issue or timeout, simply re-run the same command with -C - added. curl will send a Range: bytes=OFFSET- header and only download the remaining data. This is essential for large files over unreliable connections.
$ curl -C - -o largefile.zip https://cdn.example.com/largefile.zip

curl --limit-rate: Throttle Download Speed

What it does
The --limit-rate flag caps the download (and upload) speed to the specified rate. It accepts suffixes: k or K for kilobytes/s, m or M for megabytes/s, g or G for gigabytes/s.
Common usage
Use --limit-rate to avoid saturating your bandwidth when downloading large files, especially on shared connections. It is also useful for testing how your application handles slow responses.
$ curl --limit-rate 1M -o bigfile.iso https://mirror.example.com/bigfile.iso

curl --max-filesize: Abort if File Is Too Large

What it does
The --max-filesize flag tells curl to abort the transfer if the expected file size (from the Content-Length header) exceeds the specified limit. The size can use suffixes like k, M, G.
Common usage
Use in scripts to prevent unexpectedly large downloads from consuming disk space. Note that not all servers send Content-Length — in that case, curl cannot enforce this limit and the download proceeds normally.
$ curl --max-filesize 100M -o update.bin https://example.com/update.bin

curl -J: Use Server-Suggested Filename

What it does
The -J (or --remote-header-name) flag tells curl to use the filename specified in the server's Content-Disposition header instead of deriving it from the URL. This is common for download APIs that return files with meaningful names.
Common usage
Always combine -J with -O. This is useful when the URL is an API endpoint (like /export?format=csv) but the server returns a proper filename in the headers. Security note: the server controls the filename, so use with trusted servers only.
$ curl -L -O -J https://example.com/api/export?format=csv

curl -#: Show a Progress Bar

What it does
The -# (or --progress-bar) flag replaces the default verbose progress meter with a simple ### progress bar. This is easier to read for interactive use.
Common usage
Use -# when downloading interactively and you want a clean progress indicator. For scripts, prefer -s (silent) or the default progress meter. The default curl output already shows speed, percentage, time remaining, and total size.
$ curl -# -o archive.tar.gz https://example.com/archive.tar.gz

Additional Download Options

-u

Provide username:password for server authentication

--retry

Retry the transfer on transient errors (number of times)

--retry-delay

Wait this many seconds between retries

-T

Upload a local file to a URL (PUT by default)

--create-dirs

Create local directories as needed when saving output

-s

Suppress progress meter and error messages

--output-dir

Save output file(s) in the specified directory (curl 7.73+)

Real-World Download Scenarios

These examples combine multiple flags to handle common download tasks you will encounter in everyday development and scripting.

Download Multiple Files at Once

Use multiple -O flags to download several files in one command. curl processes them sequentially. For parallel downloads, use xargs or GNU parallel.

$ curl -O https://example.com/file1.txt -O https://example.com/file2.txt -O https://example.com/file3.txt

Download from an FTP Server

curl supports FTP, FTPS, and SFTP natively. Add -u user:password for authenticated access. Use -O to keep the remote filename.

$ curl -u user:pass -o backup.sql ftp://ftp.example.com/db/backup.sql

Download with Authentication

Use -u user:pass for Basic Auth, or -H to pass a Bearer token or API key. Combine with -L and -o for a complete download.

$ curl -H "Authorization: Bearer eyJhbGciOi..." -L -o data.json https://api.example.com/export

Reliable Download with Resume and Retry

Combine -C - (resume), --retry (automatic retry on failure), and -L (follow redirects) for robust downloads that survive network interruptions.

$ curl -C - --retry 5 --retry-delay 10 -L -o largefile.zip https://cdn.example.com/largefile.zip

Frequently Asked Questions about Downloading with curl

What is the difference between curl -o and curl -O?

-o filename saves the download to the exact filename you specify. -O extracts the filename from the URL and uses that. Use -o when you want a custom name or path; use -O when the remote filename is fine as-is.

Why does curl download an empty or HTML file instead of the actual file?

The URL likely returns an HTTP redirect (301 or 302). By default, curl saves the redirect response itself — not the final content. Add -L to follow redirects automatically: curl -L -o file URL.

How do I resume a partially downloaded file with curl?

Use curl -C - -o filename URL. The -C - flag detects the existing file size and sends a Range header to request only the remaining bytes. The server must support range requests for this to work.

How do I limit download speed in curl?

Use --limit-rate with a value and suffix: curl --limit-rate 500k -o file URL caps the speed at 500 KB/s. Suffixes: k (KB/s), M (MB/s), G (GB/s).

Can curl download multiple files at once?

Yes. Use multiple -O flags: curl -O URL1 -O URL2 -O URL3. curl downloads them sequentially. For parallel downloads, pipe a URL list to xargs -P 4 -I {} curl -O {}.

How do I download a file that requires authentication?

For HTTP Basic Auth: curl -u user:pass -o file URL. For Bearer tokens: curl -H "Authorization: Bearer TOKEN" -o file URL. For API keys in headers: curl -H "X-API-Key: KEY" -o file URL.

How do I download files from an FTP server with curl?

Use curl -u user:pass -o localfile ftp://host/path/file. curl supports FTP, FTPS (FTP over TLS), and SFTP (SSH FTP) natively. For anonymous FTP, omit -u.

How do I download large files reliably with curl?

Combine -C - (resume on failure), --retry 5 (auto-retry), --retry-delay 10, and -L (follow redirects): curl -C - --retry 5 --retry-delay 10 -L -o file URL. This handles network hiccups automatically.

How do I show a progress bar when downloading with curl?

Use curl -# -o file URL for a simple progress bar. The default curl output already shows transfer speed, percentage, and estimated time. For scripts, use -s to suppress all output.

Can I specify a download directory in curl?

With curl 7.73+, use --output-dir /path/to/dir combined with -O. For older versions, specify the full path with -o /path/to/dir/filename. Add --create-dirs if the directory does not exist yet.

Should I use curl or wget for downloading files?

Both are excellent. wget is simpler for recursive website mirroring and has built-in retry logic. curl supports 25+ protocols (not just HTTP/FTP), is better for API calls and scripting, supports more authentication methods, and is available on virtually every operating system.

How do I use curl in a bash script to download files?

Use curl -fsSL -o file URL: -f fails silently on HTTP errors (no error page saved), -s silent, -S show errors even in silent mode, -L follow redirects. Check the exit code: if ! curl -fsSL -o file URL; then echo "Download failed"; exit 1; fi.