Wget vs Curl: Which Command Should You Use?

wget vs curl: Which Command Should You Use?

Fetching a URL from a Linux shell can leave you deciding whether the response should go into a file or appear in the terminal. Wget and curl are command-line tools for transferring data to and from URLs, and they handle output differently by default.

This article compares which command fits common transfer tasks and shows how to download data or send a request.

TL;DR: wget vs curl

Use wget for saving files and retrieving linked web content, and use curl when you need control over a request or want to pipe a response into another command. Both can fetch URLs, but their defaults make different tasks convenient.

  • wget saves a downloaded resource to a file by default. curl writes the response body to standard output.
  • Use curl -o to choose a file name, or curl -O to use the remote name.
  • Wget includes recursive retrieval and background-download options. curl focuses on transfers for the URLs and requests you specify.
  • Use curl -L when you want it to follow HTTP redirects.

What are wget and curl?

GNU Wget is a command-line utility for non-interactive web downloads. curl transfers data to or from a URL, and its project also provides libcurl for applications. In this piece, I’ll compare them by task rather than assume every installation supports the same features.

Run curl --version to see curl’s protocols and build details, and use wget --version to inspect Wget’s build. Feature support can differ between GNU Wget, Wget2 and curl builds, so check installed versions before relying on an option across machines.

Which command should you use?

The table maps common transfer tasks to a starting point and explains the trade-off for each choice.

TaskBetter starting pointReason
Save one file using its URL namewgetIt writes downloads to a local file by default.
Save a curl response to a chosen pathcurlThe -o option names the destination.
Send form data or set request headerscurlIts options expose request methods, headers and data.
Retrieve a site recursivelywgetRecursive retrieval is built into Wget.
Send a response into another commandcurlIts response body goes to standard output by default.
Continue an interrupted downloadEitherBoth have continuation options, with different syntax.

A HEAD request is useful for checking response metadata before requesting the body. Servers or caches may handle HEAD and GET differently, so use GET when you need to confirm the returned content.

Use the site guide to the FTP command when you are moving files with FTP.

Inspect response metadata

The command below asks the server for response headers.

curl -I https://api.github.com/repos/curl/curl

Servers can omit Content-Type, Content-Disposition or Content-Length, so interpret the fields that actually appear in the response.

How to download and transfer data

These examples use GitHub’s public API for read-only transfers. The JSON POST URL is a placeholder. Replace it with the service you intend to call before sending data.

Download a file with wget

Wget saves a resource locally. Use -O to choose its output path, while lowercase -o names a log. In curl, lowercase -o writes the body and uppercase -O uses the remote name, so keep the tool name beside each flag when adapting a command.

wget https://api.github.com/repos/curl/curl
wget -O curl-project.json https://api.github.com/repos/curl/curl

When a URL points to a page rather than a direct file, the saved data may be HTML. Confirm that the URL serves the resource you expect before using the downloaded path in another command.

For more wget options and examples, see the Linux wget command guide. If a transfer has an IPv4 or IPv6 connectivity issue, the guide to forcing Wget to use IPv4 or IPv6 covers that narrower case. That guide also explains when the address family changes a connection attempt.

Save a curl response to a file

Use -O when the URL contains a useful filename. With -J and -O, curl can use a filename supplied by Content-Disposition, while an explicit -o path gives a script a predictable destination.

curl -o curl-project.json https://api.github.com/repos/curl/curl
curl -O https://api.github.com/repos/curl/curl

Send a request or pipe a response with curl

An API request can include a media type header and data in its body. This command shows the request shape. Replace the placeholder address with the endpoint you intend to call.

curl -H 'Content-Type: application/json' -d '{"status":"ready"}' https://api.example.com/items

The -d option sends a POST body. GNU Wget also provides --post-data and --post-file, so simple POST requests are not unique to curl. Use the method and media type specified by the API.

The pipe helps when a later command parses the response. Never send untrusted content directly to a shell or interpreter.

set -o pipefail
curl -fSs https://api.github.com/repos/curl/curl | python3 -m json.tool

In Bash, pipefail includes curl’s exit status instead of checking only Python’s. Curl’s -f treats HTTP error statuses as failures, while -sS suppresses progress and keeps error messages. json.tool formats JSON but does not check an API’s required fields.

For additional examples, see the curl download guide.

Quote the URL so the shell passes the ampersand as part of one argument.

curl -o results.json 'https://api.github.com/search/repositories?q=wget&per_page=1'

Use the shell’s quoting syntax when a URL itself contains a quote.

Download several known URLs

Put one URL on each line of the input file. Check the list before running it because each entry can trigger a network request.

wget -i urls.txt

After the batch finishes, check its exit status and expected files before letting a later step use them. Choose explicit destinations when another command depends on fixed paths.

Run a long Wget download in the background

Wget’s -b option starts the transfer in the background, returning the prompt while Wget continues.

wget -b https://api.github.com/repos/curl/curl

Check the log and output file when the transfer finishes. Keep short jobs in the foreground when a script needs to react to failure. The site’s nohup guide explains another way to keep a process running after a shell session ends.

These options reflect Wget’s download workflow. curl can still perform the transfers in a shell-managed background process, but job control then comes from the shell or process supervisor rather than a built-in recursive or background download mode.

Defaults and edge cases to check

Redirect behavior, HTTP status handling, filenames and continuation behavior can affect a transfer. Check those details before depending on the result in a script.

Redirects do not follow the same default

Wget follows HTTP redirects by default. curl needs -L to request the redirected resource.

curl -L -o redirect.json https://httpbin.org/redirect/1

I ran the redirect example in this refresh. It saved JSON with the final URL https://httpbin.org/get.

Follow redirects only when the destination is expected, especially for requests that include credentials or sensitive data.

A transfer can succeed while the HTTP request fails

curl’s fail option returns an error when the server sends an HTTP status of 400 or higher. Use it when a script must stop instead of passing a server-error page onward. Redirect handling is separate.

SituationSymptomResponse
Server returns HTTP 4xx or 5xxResponse body exists but request is unsuccessfulRecord response status separately from the transfer exit code.
Batch or script calls several URLsOne file exists although a transfer failedCheck final status and expected output files. Do not trust file presence alone.

Resume only when the server supports it

The continuation option requests more data after the local partial file.

ToolContinuation formRequirement
wgetwget -c URLRemote server must support range requests for continuation.
curlcurl -C – -O URLLocal partial file must match the remote resource and the server must support ranges.

If the remote object changed during interruption, remove or rename the partial file before retrying, because appending bytes from two versions corrupts the result.

Recursive retrieval is a different job from fetching a URL

Use recursion only when the site permits retrieval of its linked pages.

TaskWhat happensChoice
Fetch a known URLOne specified resource is requestedEither tool can work. Choose by output and request needs.
Retrieve linked pages recursivelyMore URLs may be discovered and fetchedWget has recursive retrieval options.

Confirm access rules and decide whether a static offline copy is complete. Wget does not execute JavaScript, so dynamic interfaces may not be represented.

Retries do not replace an error policy

Retries help with transient connection failures, not malformed requests or permanent HTTP errors.

Failure typeWhat the command seesSafer handling
Connection interruptionTransfer may stop before all bytes arriveUse a bounded retry policy, then verify the resulting file.
HTTP error responseServer returned a response that may include an error bodyCheck status handling and exit status, then decide whether retrying fits the service.
Invalid or changed resourceA retry can fetch different content or repeat a permanent failureCheck the URL and resource identity before retrying.
wget --tries=3 https://api.github.com/repos/curl/curl
curl --retry 3 -o curl-project.json https://api.github.com/repos/curl/curl

These examples cap attempts for a file URL. Set a timeout as well when a scheduled task must finish within a defined window, then report the final exit status to the calling script.

Limit transfer bandwidth without confusing it with API quotas

Both tools can cap transfer speed. This is a byte-rate ceiling, not a per-request delay or API quota.

wget --limit-rate=300k https://api.github.com/repos/curl/curl
curl --limit-rate 300k -o curl-project.json https://api.github.com/repos/curl/curl

Keep credentials out of command arguments

Use documented authentication methods, and keep secrets out of plain command strings.

RiskWhy it mattersSafer practice
Credentials in a URLThey can appear in process information or logs.Use the client’s documented authentication mechanism and protect any credential file with restrictive permissions.
Secrets in shell historyA command may remain in the user’s history file.Use a credential store or another protected input mechanism suited to the environment.
TLS certificate errorThe URL, local trust store or server certificate may need attention.Correct the certificate configuration and keep verification enabled.

Conclusion

Start with the expected result: a file on disk, a response passed to another program, or a request with custom headers or data. Pick the tool whose defaults fit, then check the exit status and output before the next step consumes them.

For further reference, read the GNU Wget manual and the curl command manual. To learn how to use the manual-page viewer locally, see the site’s guide to the man command.

FAQ

These answers cover the defaults and choices that tend to cause confusion.

Can wget and curl transfer files over FTP?

GNU Wget supports FTP retrieval, and curl supports FTP when its build includes that protocol. Check the installed build if FTP support is required.

Why should I keep a password out of a transfer URL?

A password in a command-line URL can be visible in process listings or logs. Use a documented authentication method and protect any credential input.

Can both tools send a POST request?

Yes. Both support simple POST requests, but their options differ. Match the API’s required method and content type.

Is Wget2 the same as GNU Wget?

No. Wget2 is a separate release line. Check which executable and local manual your system provides before relying on an option.