Skip to content

cURL vs Wget: the differences and which to use with a proxy

We ran curl and Wget side by side. Wget resumed a broken download alone, curl -Z was nine times faster on 1,000 files, and only curl took SOCKS5.

HProxy TeamOctober 11, 2026Updated October 11, 202610 min read

cURL vs Wget: the differences and which to use with a proxy

curl and Wget both fetch files from the command line, and they differ from the first command. curl prints the answer and does only what you ask. Wget saves files, follows redirects, picks up broken downloads and can copy a whole site. With proxies, curl does everything Wget does and adds SOCKS5.

We ran both side by side on 11 October 2026: curl 8.5.0 and GNU Wget 1.21.4, against httpbin.org, a public echo service, and small test servers of our own. Every result below comes from that run.

What is the difference between curl and Wget?

The short version comes from Daniel Stenberg, who wrote curl and also contributes to Wget: "curl works more like the traditional Unix cat command", while "Wget is more like cp". One sends data where you point it. The other makes files.

We ran each one without extra options:

curl 8.5.0GNU Wget 1.21.4
The answerprinted to the terminalsaved as a file
A redirectstops at it, -L followsfollowed, up to 20
A download that breaksstops, exit code 18continues from the break
A 503 from the serverone request, exit code 0one request, exit code 8
A 404saves the error page, exit code 0saves nothing, exit code 8
HTTP version, to a site that offers HTTP/2HTTP/2HTTP/1.1
User-Agentcurl/8.5.0Wget/1.21.4
Copying a whole sitenowith -r
Many files at oncewith -Z, 50 at a timeone after another
SOCKS5 proxiesyesno
Uploadsthe raw file or a multipart formthe file, sent as a form

The sections below show each test.

Which one follows redirects?

Wget does, and curl does not until you add -L. On a page that redirected twice, curl stopped at the first 302, and Wget followed both. Wget's manual sets its limit: "The default is 20, which is usually far more than necessary." curl's -L makes it "redo the request to the new place".

This explains a common puzzle: curl -O saves a tiny file where Wget saves the real one. curl saves whatever the first answer was:

$ curl -O https://httpbin.org/redirect/1
  exit code 0; saved:
    1, 215 bytes, starting: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><title>Redirec
$ curl -L -O https://httpbin.org/redirect/1
  exit code 0; saved:
    1, 255 bytes, starting: { "args": {}, "headers": { "Accept": "*/*", "Host": "htt
$ wget https://httpbin.org/redirect/1
  exit code 0; saved:
    1, 292 bytes, starting: { "args": {}, "headers": { "Accept": "*/*", "Accept-Enco

The 215-byte file is httpbin's "Redirecting..." page, not the content. Add -L, and curl saves the same file Wget does.

What happens when a download breaks?

Wget picks it up on its own. curl stops. We built a small server that cuts the first download of a 20 MB file after 5 MB and answers normally after that. A fresh server ran for each case:

Terminal output: Wget continues a broken download from byte 5242880 with a 206 answer; curl stops with exit code 18; curl --retry 3 does not retry; curl --retry-all-errors downloads the whole file again; the server's log of each request
Our own capture, 11 October 2026: broken.sh with curl 8.5.0 and GNU Wget 1.21.4 on our server, cases 1 to 4 of 7
  • Wget printed "Connection closed at byte 5242880. Retrying." and asked for the rest, from byte 5,242,880. The file came out complete, with the same SHA-256 checksum as the original.
  • curl stopped with exit code 18 and a 5 MB file.
  • curl --retry 3 did not retry. A broken transfer is not one of the errors it retries. The manual lists those: "a timeout, an FTP 4xx response code or an HTTP 408, 429, 500, 502, 503, 504, 522 or 524 response code".
  • curl --retry-all-errors retried, but downloaded the whole file again from byte 0, even with -C -. The manual warns that "before retrying it removes output data from a failed partial transfer that was written to an output file".

Daniel Stenberg's comparison says the same: Wget's "ability to recover from a prematurely broken transfer and continue downloading has no counterpart in curl". That holds for curl 8.5.0, released on 6 December 2023. curl's changelog for 8.17.0, released on 5 November 2025, lists "keep failed partial download for retry auto-resume", so newer versions may resume on a retry.

By hand, both resume. After a break, curl -C - -o file.bin URL and wget -c URL both asked the server for bytes=5242880- and finished the file. The server answers such a request with 206 Partial Content, which RFC 9110 describes as "successfully fulfilling a range request for the target resource".

Does either one retry server errors?

Not by default. A page that answered 503 got one request from each tool. Wget's tries are for network failures: "The default is to retry 20 times". Its manual calls 503 and 429 errors "normally not retried by Wget", and offers --retry-on-http-error for them.

curl retried the 503 with --retry 3: four requests in all, with waits of 1, 2 and 4 seconds. Its exit code stayed 0, though. Without -f, curl counts any answer from the server as a success. On a 404 it saved the error page and exited 0; with -f it exited 22 and saved nothing. Wget exited 8 on both. In a script, give curl -f, or check Wget's exit code.

Can curl download a whole site like Wget?

No. In Daniel Stenberg's words, curl "transfers just the URLs that the user specifies, and does not contain any recursive downloading logic nor any sort of HTML parser". Wget does. We built a five-page test site and ran wget -r -l 2 on it:

$ wget -r -l 2 http://127.0.0.1:PORT/
  (Wget's progress lines left out)
  exit code 0; files saved:
    ./127.0.0.1:PORT/a.html
    ./127.0.0.1:PORT/c.html
    ./127.0.0.1:PORT/img.png
    ./127.0.0.1:PORT/index.html
    ./127.0.0.1:PORT/robots.txt
    ./127.0.0.1:PORT/style.css
  the server's log, in order:
    GET / HTTP/1.1 -> 200 (User-Agent: Wget/1.21.4)
    GET /robots.txt HTTP/1.1 -> 200 (User-Agent: Wget/1.21.4)
    GET /style.css HTTP/1.1 -> 200 (User-Agent: Wget/1.21.4)
    GET /a.html HTTP/1.1 -> 200 (User-Agent: Wget/1.21.4)
    GET /img.png HTTP/1.1 -> 200 (User-Agent: Wget/1.21.4)
    GET /c.html HTTP/1.1 -> 200 (User-Agent: Wget/1.21.4)

Wget read robots.txt right after the first page, and skipped b.html, which robots.txt disallows. Its manual says so: "Wget respects the Robot Exclusion Standard (/robots.txt)". It followed the stylesheet to the image, and it did not leave the host for the link to example.com. curl -O on the same site saved index.html and nothing else.

Which one is faster?

For one big file, neither. We downloaded Linode's public 100 MB test file ten times with each tool, taking turns. curl's median was 10.3 seconds and Wget's 8.0, but each tool's slowest run took about three times its fastest. The network decided, not the tool.

For many small files, curl's parallel mode wins. Daniel Stenberg: "curl can do many transfers in parallel (-Z). Wget only does serial." We served 1,000 files of 10 KiB from a test server on the same machine and timed five runs of each command:

Time for 1,000 files of 10 KiB, median of five runs (seconds)
curl -Z, 50 at once
0.13 s
curl, one command
0.74 s
wget -i, one list
1.23 s
Parallel transfers are where curl pulls ahead. Wget fetches one file after another.
Source: HProxy test, 11 October 2026: curl 8.5.0 and GNU Wget 1.21.4 against a Node server on 127.0.0.1, on our server · hproxy.comProxy.

Without -Z, both used a single connection for all 1,000 files, and curl's command was faster than Wget's list in all five rounds. With -Z, curl opened 50 connections and finished about nine times faster than Wget.

Which one works better with a proxy?

Both work with an ordinary HTTP proxy. We ran each through small logging proxies of our own:

  • On the command line: curl -x http://host:port and wget -e use_proxy=yes -e https_proxy=http://host:port.
  • From the environment: both read the https_proxy variable.
  • With a login: curl -U user:pass, and wget --proxy-user=user --proxy-password=pass or the login inside the proxy address. Both sent the login with their first request to the proxy.

Without the login, curl reported a 407 and Wget "Proxy tunneling failed". Each tool also showed the proxy its User-Agent, curl/8.5.0 and Wget/1.21.4. Our residential proxies work with either tool as an HTTP proxy with a login.

SOCKS5 is where they part:

Terminal output: curl through a SOCKS5 proxy with socks5h, which sends the host name, and with socks5, which sends an address curl resolved itself; Wget refusing socks5 with Unsupported scheme
Our own capture, 11 October 2026: proxies.sh with curl 8.5.0 and GNU Wget 1.21.4 on our server, part 4 of 4

curl worked both ways. With socks5h://, it handed the proxy the host name. With socks5://, it sent an address it had looked up itself. The SOCKS5 standard, RFC 1928, has its own address type for the first case: "the address field contains a fully-qualified domain name". Pick socks5h:// when the proxy should do the lookup: the manual says it lets "the proxy resolve the hostname".

Wget refused with "Unsupported scheme" and never contacted the proxy. Daniel Stenberg's comparison is blunt: "Wget has no SOCKS support." Our guide to proxies with wget shows the wrapper route.

What else is different?

  • The TLS handshake. curl offered 31 cipher suites and listed h2 and http/1.1 in its ALPN extension, then spoke HTTP/2. Wget offered 75 cipher suites and no ALPN, and spoke HTTP/1.1. Their JA4 fingerprints, t13d3112h2_e8f1e7e78f70_b26ce05bbdd6 and t13d7511_479067518aa3_fb8d5ffd48c1, differ in every count and both hashes, so a site that reads them can tell the two apart. See cURL user agent for why a browser User-Agent does not change that.
  • Uploads. curl -T sent a file as it was, and curl -F sent it as a multipart form, the way a browser uploads. Wget sent it with --method=PUT --body-file, but labelled it a form, so the test server read the file as a form field. Its manual says Wget does not support multipart form data.
  • The letter -U. In Wget it sets the User-Agent. In curl it is the proxy login: curl -U "my-agent/1.0" stopped and asked "Enter proxy password for user 'my-agent/1.0':".
  • Where they come from. "curl comes pre-installed on macOS and Windows 10/11. Wget does not." "curl is powered by libcurl", a library other programs build on, while "Wget is command line only." Their licenses differ too: "Wget is GPL v3. curl is MIT licensed."

Which flags do the same job?

TaskcurlWget
Save under the remote namecurl -O URLwget URL
Print to the terminalcurl URLwget -qO- URL
Follow redirects-Lon by default
Resume a partial file-C --c
Retry after a timeout--retry 3on by default
Continue a broken download by itselfno: --retry-all-errors starts overon by default
Retry a 503--retry 3--retry-on-http-error=503
Fail on an HTTP error-fon by default
Set the User-Agent-A "name"-U "name"
Use an HTTP proxy-x http://host:port-e use_proxy=yes -e https_proxy=http://host:port
Proxy login-U user:pass--proxy-user=user --proxy-password=pass
SOCKS5 proxy-x socks5h://host:portnot supported
Skip the certificate check-k--no-check-certificate
Many files at once-Znot supported
Copy a whole sitenot supported-r

The certificate options do what their names say. curl's manual: -k "makes curl skip the verification step and proceed without checking". Our page on curl -k covers when that is safe.

Which should you use?

  • To download files and walk away, use Wget. It follows redirects and picks up broken downloads without extra options, and copies whole sites with -r.
  • For APIs, scripts and control over the request, use curl. Headers, uploads and parallel transfers are all built in.
  • Behind a SOCKS5 proxy, use curl. Behind an HTTP proxy, either one works.

What this page could not check

  • One server, curl 8.5.0 and GNU Wget 1.21.4. Newer versions may differ: curl 8.17.0 changed how a retry treats a partial download.
  • Our test servers and proxies are small ones of our own. Real servers and proxies may answer differently.
  • The big-file times depend on the network path and on the server's other work at that moment.
  • We will run the tests again by 11 January 2027.

Sources

  • Daniel Stenberg, curl vs Wget, read 11 October 2026: daniel.haxx.se.
  • GNU Wget manual, version 1.21.4 as installed on our server, read 11 October 2026: gnu.org.
  • curl, man page, -L, --retry, --retry-all-errors, -C, -Z, -k and the SOCKS options, read 11 October 2026: curl.se.
  • curl, changelog for 8.5.0 and 8.17.0, read 11 October 2026: curl.se.
  • RFC 1928, SOCKS Protocol Version 5, IETF, March 1996: rfc-editor.org.
  • RFC 9110, HTTP Semantics, 206 Partial Content, IETF, June 2022: rfc-editor.org.
  • FoxIO, JA4 technical details, read 11 October 2026: github.com.
  • Our own tests on our server, 11 October 2026: defaults.sh at 16:06 UTC, broken.sh at 16:08 UTC, proxies.sh and mirror.sh at 16:11 UTC, speed.sh at 16:18 UTC, more.sh at 16:24 UTC.

Frequently asked questions

What is the difference between curl and wget?

curl sends a request and prints the answer, which suits scripts and APIs. Wget saves files, follows redirects on its own, continues broken downloads and can copy a whole site. Only curl works with SOCKS5 proxies and runs transfers in parallel.

Is wget faster than curl?

Not for one file. In ten runs each on a 100 MB file, neither won, and each tool's slowest run took about three times its fastest. For 1,000 small files, curl -Z took 0.13 s against 1.23 s for wget -i.

Why does curl -O save a tiny file when wget works?

curl does not follow redirects unless you add -L. In our test, curl -O saved a 215-byte redirect page instead of the file. curl -L -O and wget both saved the real file.

Does wget support SOCKS5 proxies?

No. Wget 1.21.4 answered a socks5:// proxy address with Unsupported scheme and never contacted the proxy. curl works with both socks5:// and socks5h://.

Does wget retry failed downloads?

It retries network failures, 20 times by default, and continues a broken download where it stopped. It does not retry HTTP errors such as 503 unless you list them with --retry-on-http-error.

What is the curl equivalent of wget --no-check-certificate?

-k, also written --insecure. Like the Wget option, it makes curl skip the certificate check and go on without it.

Get proxies that are alive right now

Our free proxy list re-checks every exit every few minutes across 100+ countries, with a live last-checked time, so you copy IPs that worked moments ago, not a stale text dump. When the location has to survive a real check, the paid network holds up.

129M+ proxy checks run · 100+ countries · HTTP / HTTPS / SOCKS · re-checked every few minutes · no signup

HProxy.

Honest guides and comparisons on proxies, scraping and staying unblocked, from the team that runs the network.

RSS feed