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
Write output to a named file instead of stdout
Write output to a file named like the remote file
Follow HTTP 3xx redirects automatically
Continue/resume a previous file transfer
Limit the transfer speed to the given rate
Refuse to download files larger than the specified size
Use the Content-Disposition header to name the file
Display transfer progress as a simple progress bar
Provide username:password for server authentication
Retry the transfer on transient errors (number of times)
Wait this many seconds between retries
Upload a local file to a URL (PUT by default)
Create local directories as needed when saving output
Suppress progress meter and error messages
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
-owhen 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-Lto handle redirects and-sfor silent operation in scripts.
$ curl -o report.pdf https://example.com/files/report.pdfcurl -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 calleddata.csvin the current directory. - Common usage
- Use
-Owhen the remote filename is meaningful and you don't need to rename it. You can pass multiple-Oflags to download several files in one command. Note: if the URL doesn't contain a filename (e.g., ends with/), curl will fail — use-oinstead.
$ curl -O https://example.com/files/data.csvcurl -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
-Lwith-oor-Owhen 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.gzcurl -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 HTTPRangeheader 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 aRange: 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.zipcurl --limit-rate: Throttle Download Speed
- What it does
- The
--limit-rateflag caps the download (and upload) speed to the specified rate. It accepts suffixes:korKfor kilobytes/s,morMfor megabytes/s,gorGfor gigabytes/s. - Common usage
- Use
--limit-rateto 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.isocurl --max-filesize: Abort if File Is Too Large
- What it does
- The
--max-filesizeflag tells curl to abort the transfer if the expected file size (from theContent-Lengthheader) exceeds the specified limit. The size can use suffixes likek,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.bincurl -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'sContent-Dispositionheader instead of deriving it from the URL. This is common for download APIs that return files with meaningful names. - Common usage
- Always combine
-Jwith-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=csvcurl -#: 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.gzAdditional Download Options
Provide username:password for server authentication
Retry the transfer on transient errors (number of times)
Wait this many seconds between retries
Upload a local file to a URL (PUT by default)
Create local directories as needed when saving output
Suppress progress meter and error messages
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.txtDownload 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.sqlDownload 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/exportReliable 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.zipFrequently 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.