cURL & Wget — Complete Guide

A comprehensive practical guide covering command-line data transfer tools: cURL (Client URL) and Wget (World Wide Web Get).


1. Overview & Comparison

Both cURL and Wget are command-line utilities used for downloading data and interacting with servers over network protocols (HTTP, HTTPS, FTP, etc.).

flowchart LR subgraph cURL["cURL (API & Protocol Powerhouse)"] direction TB C1["Bidirectional (Transfer & Receive)"] C2["REST API Testing & Debugging"] C3["Supports 25+ Protocols"] C4["Powered by libcurl"] end subgraph Wget["Wget (File & Web Crawler Specialist)"] direction TB W1["Non-interactive Background Downloads"] W2["Recursive Web Crawling & Mirroring"] W3["Automatic Retry & Resume Support"] W4["Simple CLI for Bulk File Fetching"] end

Key Differences

Feature cURL (curl) Wget (wget)
Primary Focus Data transfer, API testing, HTTP methods File downloads, site mirroring
Direction Bidirectional (Upload + Download) Primarily Download
HTTP Methods Full support (GET, POST, PUT, DELETE, etc.) Limited (GET, basic POST)
Recursive Download ❌ No ✅ Yes (-r, --mirror)
Protocol Support 25+ (HTTP, HTTPS, FTP, SFTP, LDAP, SCP, etc.) HTTP, HTTPS, FTP, FTPS
Library Built on libcurl (usable in code) Standalone executable
Piping & stdout Defaults to stdout Defaults to file on disk
Background execution Manual (& or nohup) Built-in (-b)

2. cURL (curl) In-Depth

curl is designed to transfer data to or from a server using one of the supported protocols.

Common Flags & Options

Flag Long Flag Description
-X --request Specify HTTP request method (GET, POST, PUT, DELETE)
-H --header Pass custom HTTP header (e.g., -H "Content-Type: application/json")
-d --data Send data in POST/PUT request body
-o --output Write output to specified file
-O --remote-name Write output to a local file named like the remote file
-i --include Include HTTP response headers in the output
-I --head Fetch response headers only (HEAD request)
-L --location Follow HTTP 3xx redirects automatically
-u --user Specify user credentials (user:password)
-v --verbose Make the operation verbose (debugging info)
-s --silent Silent mode (no progress meter or error messages)
-k --insecure Allow insecure SSL connections (skip cert validation)
-C --continue-at Resume a previously interrupted download
-F --form Send multipart form data (file uploads)
-b --cookie Send cookies from string or file
-c --cookie-jar Save received cookies to file

HTTP Request Examples

1. Basic GET Request

curl https://api.example.com/users

2. Save Output to File

# Save to specific filename
curl -o user_data.json https://api.example.com/users

# Save using remote file's original name
curl -O https://example.com/downloads/archive.tar.gz

3. POST Request with JSON Data

curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name": "John Doe", "email": "john@example.com"}'

4. POST Request with Data from File

curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d @payload.json

5. PUT Request (Update Resource)

curl -X PUT https://api.example.com/users/123 \
  -H "Content-Type: application/json" \
  -d '{"name": "Jane Doe", "email": "jane@example.com"}'

6. PATCH Request (Partial Update)

curl -X PATCH https://api.example.com/users/123 \
  -H "Content-Type: application/json" \
  -d '{"email": "newemail@example.com"}'

7. DELETE Request

curl -X DELETE https://api.example.com/users/123

8. Follow Redirects (301 / 302)

curl -L http://example.com

Authentication & Headers

1. Bearer Token Authentication

curl -H "Authorization: Bearer YOUR_API_TOKEN" https://api.example.com/protected

2. Basic Authentication

curl -u username:password https://api.example.com/dashboard

3. Custom Headers

curl -H "X-Custom-Header: CustomValue" \
  -H "Accept-Language: en-US" \
  https://api.example.com/data

4. API Key Header

curl -H "x-api-key: secret-api-key-12345" https://api.example.com/v1/metrics

File Uploads & Forms

1. Multipart Form Upload (multipart/form-data)

curl -F "file=@/path/to/photo.jpg" \
  -F "description=Profile Photo" \
  https://api.example.com/upload

2. Standard Form URL-Encoded (application/x-www-form-urlencoded)

curl -d "username=admin" \
  -d "password=secret" \
  https://example.com/login

Cookies & Sessions

1. Save Cookies to a File

curl -c cookies.txt -d "user=admin&pass=123" https://example.com/login

2. Send Cookies with Request

curl -b cookies.txt https://example.com/dashboard
curl -b "session_id=abc123xyz; dark_mode=true" https://example.com/preferences

Debugging, Metrics & Performance

1. Inspect Response Headers Only

curl -I https://example.com

2. Include Headers with Response Body

curl -i https://api.example.com/users

3. Verbose Network Tracing

curl -v https://api.example.com/users

4. Formatted Timing Metrics (-w)

curl -s -w "\
HTTP Code:       %{http_code}\n\
DNS Lookup:      %{time_namelookup}s\n\
TCP Connect:     %{time_connect}s\n\
TLS Handshake:   %{time_appconnect}s\n\
Pre-transfer:    %{time_pretransfer}s\n\
Start Transfer:  %{time_starttransfer}s\n\
Total Time:      %{time_total}s\n" \
-o /dev/null https://google.com

5. Rate Limiting & Resuming Downloads

# Limit download speed to 500 KB/s
curl --limit-rate 500k -O https://example.com/largefile.zip

# Resume interrupted download
curl -C - -O https://example.com/largefile.zip

3. Wget (wget) In-Depth

wget is a free, non-interactive network downloader that supports HTTP, HTTPS, and FTP protocols.

Common Flags & Options

Flag Long Flag Description
-O --output-document Concatenate output and write to specified file
-P --directory-prefix Save files to a specific directory
-c --continue Resume getting a partially-downloaded file
-b --background Go to background immediately after startup
-r --recursive Turn on recursive retrieving
-l --level Maximum recursion depth (default 5, 0 or inf for infinite)
-m --mirror Turn on options suitable for mirroring (-r -N -l inf --no-remove-listing)
-k --convert-links Make links in downloaded HTML point to local files
-p --page-requisites Download all images, CSS, etc. needed to display HTML page
-np --no-parent Don't ascend to parent directory when retrieving recursively
-i --input-file Read URLs from a local or external file
-A --accept Comma-separated list of accepted file extensions
-R --reject Comma-separated list of rejected file extensions
-t --tries Set number of retries (0 or inf for infinite)
-Q --quota Set download quota (e.g., 100m)
--limit-rate --limit-rate Limit download rate (e.g., 200k, 2m)

Downloading Files

1. Download a Single File

wget https://example.com/files/document.pdf

2. Download and Save with Custom Name

wget -O custom_name.pdf https://example.com/files/document.pdf

3. Save into Specific Folder

wget -P /path/to/downloads https://example.com/files/document.pdf

4. Resume an Interrupted Download

wget -c https://example.com/files/large_archive.iso

5. Download in the Background

wget -b https://example.com/files/large_archive.iso

# View download progress in log
tail -f wget-log

6. Download Multiple Files from a URL List

wget -i urls.txt

Website Crawling & Mirroring

1. Mirror an Entire Website for Offline Viewing

wget --mirror --convert-links --adjust-extension --page-requisites --no-parent https://example.com/
  • --mirror (-m): Enables recursion, timestamps, and infinite depth.
  • --convert-links (-k): Converts links to point to local files.
  • --adjust-extension (-E): Appends .html to files if needed.
  • --page-requisites (-p): Downloads all CSS, JS, and image assets.
  • --no-parent (-np): Restricts downloads to the current subpath.

2. Download Specific File Types (e.g., all PDFs)

wget -r -A.pdf -np https://example.com/documents/

3. Reject Specific File Types

wget -r -R.zip,.tar.gz https://example.com/files/

Authentication & Rate Limiting

1. Basic HTTP Authentication

wget --http-user="myuser" --http-password="mypassword" https://example.com/secure/file.zip

2. Custom Request Header

wget --header="Authorization: Bearer YOUR_TOKEN" https://example.com/api/export.csv

3. Limit Download Speed & Retries

wget --limit-rate=1m --tries=10 --timeout=30 https://example.com/video.mp4

4. Side-by-Side Command Cheatsheet

Task cURL (curl) Wget (wget)
Download file to disk curl -O <url> wget <url>
Download with custom name curl -o file.zip <url> wget -O file.zip <url>
Save to directory curl -o dir/file.zip <url> wget -P dir/ <url>
Resume download curl -C - -O <url> wget -c <url>
Limit download rate curl --limit-rate 500k -O <url> wget --limit-rate=500k <url>
Fetch headers only curl -I <url> wget --spider -S <url>
Send GET request curl <url> wget -qO- <url>
Send POST JSON curl -X POST -H "Content-Type: application/json" -d '{"k":"v"}' <url> wget --post-data='{"k":"v"}' --header="Content-Type: application/json" <url>
Bearer token auth curl -H "Authorization: Bearer <token>" <url> wget --header="Authorization: Bearer <token>" <url>
Basic auth curl -u user:pass <url> wget --user=user --password=pass <url>
Follow redirects curl -L <url> Automatic (default)
Silent output curl -s <url> wget -q <url>
Ignore invalid SSL cert curl -k <url> wget --no-check-certificate <url>
Recursive download ❌ Not supported wget -r -np -A.pdf <url>
Offline website mirror ❌ Not supported wget -mkEp <url>

5. Practical Automation Recipes

1. API Health Check Script (curl)

#!/usr/bin/env bash

ENDPOINT="https://api.example.com/health"
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$ENDPOINT")

if [ "$HTTP_STATUS" -eq 200 ]; then
  echo "✅ Endpoint is healthy (HTTP $HTTP_STATUS)"
else
  echo "❌ Endpoint failed with status HTTP $HTTP_STATUS"
  exit 1
fi

2. Formatted JSON API Query with jq (curl)

curl -s -H "Accept: application/json" https://jsonplaceholder.typicode.com/todos/1 | jq .

3. Bulk Document Downloader (wget)

#!/usr/bin/env bash

# Downloads all PDFs from a target directory with retry and rate limit
TARGET_URL="https://example.com/whitepapers/"

wget -r -l 2 -np -nc \
  -A "*.pdf" \
  --limit-rate=2m \
  --tries=5 \
  --wait=1 \
  -P ./whitepapers/ \
  "$TARGET_URL"

6. Summary: When to Choose Which?

flowchart TD Start{"What is your primary goal?"} Start -- "API Testing & REST Operations" --> cURL["Use cURL"] Start -- "Bulk Files & Site Mirroring" --> Wget["Use Wget"] subgraph cURL_Scope["cURL Capabilities"] cURL --> C1["• Full HTTP verbs: GET, POST, PUT, DELETE"] cURL --> C2["• Custom headers & JSON payloads"] cURL --> C3["• Timing & handshake metrics (-w)"] end subgraph Wget_Scope["Wget Capabilities"] Wget --> W1["• Recursive site crawling & mirroring (-m)"] Wget --> W2["• Non-interactive background downloads (-b)"] Wget --> W3["• Automatic retries & resume on disconnect (-c)"] end