🌐 Linux curl Command

Transfer Data with URLs - Examples by Claude

What is curl?

The curl command is a powerful tool for transferring data to or from a server using URLs. It supports numerous protocols including HTTP, HTTPS, FTP, FTPS, SCP, SFTP, TFTP, LDAP, and many more. The name stands for "Client URL" or "see URL". It's an essential tool for developers, sysadmins, and anyone working with web services, APIs, or network operations. Think of it as a command-line web browser that can do much more than just browse.

Example 1Basic GET Request

curl https://example.com
Fetches the content from a URL and displays it in the terminal. This is the simplest use of curl - just retrieve a web page.
<!doctype html> <html> <head> <title>Example Domain</title> </head> <body> <h1>Example Domain</h1> <p>This domain is for use in illustrative examples...</p> </body> </html>

Example 2Save Output to File

curl -o myfile.html https://example.com
Download content and save it to a specific filename using -o (lowercase). This gives you control over the output filename.
Pro Tip: Use -O (uppercase) to save with the remote filename: curl -O https://example.com/file.pdf

Example 3Follow Redirects

curl -L https://github.com
The -L flag tells curl to follow HTTP redirects. Many URLs redirect (301, 302 responses), and without -L, curl stops at the redirect.
Note: This is one of the most commonly needed flags. Many modern websites use redirects extensively.

Example 4Show Response Headers

curl -I https://example.com
Display only the HTTP headers using -I (HEAD request). Great for checking server responses, content type, and status codes without downloading the body.
HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 02 Nov 2025 14:30:00 GMT server: Apache/2.4.41 content-length: 1256 last-modified: Thu, 17 Oct 2025 07:18:26 GMT

Example 5Include Headers in Output

curl -i https://example.com
Display both headers AND body content using -i. Useful when you need to see the full HTTP response.

Example 6Verbose Mode for Debugging

curl -v https://example.com
Enable verbose mode with -v to see detailed information about the connection, SSL handshake, request headers, and response. Essential for debugging.
* Trying 93.184.216.34:443... * Connected to example.com (93.184.216.34) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): ... > GET / HTTP/2 > Host: example.com > User-Agent: curl/7.68.0 > Accept: */* < HTTP/2 200
Pro Tip: Use --trace or --trace-ascii for even more detailed debugging output.

Example 7POST Request with Data

curl -X POST -d "name=John&email=john@example.com" https://api.example.com/users
Send a POST request with form data using -d. The -X flag specifies the HTTP method (though -d implies POST, so -X POST is optional here).
Note: -d sends data as application/x-www-form-urlencoded by default

Example 8POST JSON Data

curl -X POST -H "Content-Type: application/json" -d '{"name":"John","email":"john@example.com"}' https://api.example.com/users
Send JSON data to an API. Use -H to set the Content-Type header and -d for the JSON payload. This is how you interact with RESTful APIs.
Pro Tip: Use single quotes around JSON to avoid shell interpretation issues with double quotes.

Example 9Send JSON from File

curl -X POST -H "Content-Type: application/json" -d @data.json https://api.example.com/users
Read data from a file using @filename syntax. The @ tells curl to read the content from the specified file.

Example 10Basic Authentication

curl -u username:password https://api.example.com/secure
Provide HTTP Basic Authentication credentials using -u. The credentials are sent in the Authorization header.
Security Warning: This exposes passwords in command history. Use -u username (without password) to be prompted, or use environment variables.

Example 11Set Custom Headers

curl -H "Authorization: Bearer YOUR_TOKEN" -H "Accept: application/json" https://api.example.com/data
Add custom HTTP headers using -H. You can specify multiple headers by using -H multiple times. Essential for API authentication tokens.

Example 12Upload a File

curl -F "file=@/path/to/file.pdf" https://api.example.com/upload
Upload a file using multipart/form-data with -F flag. The @ prefix indicates a file path.

Example 13Download with Progress Bar

curl -# -O https://example.com/largefile.zip
Show a simple progress bar instead of the detailed progress meter using -#. Useful for large downloads where you just want to see percentage complete.
######################################################################## 100.0%

Example 14Resume Interrupted Download

curl -C - -O https://example.com/largefile.zip
Resume a partially downloaded file using -C -. The dash tells curl to automatically determine where to resume from.
Pro Tip: This only works if the server supports range requests (most modern servers do).

Example 15Set User Agent

curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" https://example.com
Change the User-Agent header using -A. Some websites serve different content based on the user agent.

Example 16Use Cookies

curl -b cookies.txt https://example.com
Send cookies from a file using -b. Useful for maintaining sessions across requests.
# Save cookies to file
curl -c cookies.txt https://example.com/login

# Use saved cookies
curl -b cookies.txt https://example.com/dashboard

Example 17Follow Redirects with Max Limit

curl -L --max-redirs 5 https://example.com
Follow redirects but limit the maximum number to prevent infinite redirect loops. Default is 50 if not specified.

Example 18Test API Response Time

curl -w "@curl-format.txt" -o /dev/null -s https://api.example.com
Measure various timing metrics using -w with a format file. The -o /dev/null discards the output, -s silences progress.
# Create curl-format.txt with:
time_namelookup:  %{time_namelookup}s\n
time_connect:     %{time_connect}s\n
time_appconnect:  %{time_appconnect}s\n
time_pretransfer: %{time_pretransfer}s\n
time_redirect:    %{time_redirect}s\n
time_starttransfer: %{time_starttransfer}s\n
time_total:       %{time_total}s\n
time_namelookup: 0.001s time_connect: 0.025s time_appconnect: 0.156s time_pretransfer: 0.156s time_redirect: 0.000s time_starttransfer: 0.234s time_total: 0.245s

Example 19Silent Mode (No Progress)

curl -s https://api.example.com/status | jq .
Suppress progress meter and error messages with -s. Perfect for piping output to other commands like jq for JSON parsing.

Example 20Only Show Errors (Silent but Show Errors)

curl -sS https://api.example.com/data
Combine -s (silent) with -S (show errors) to hide progress but still display errors. Best of both worlds for scripting.

Example 21DELETE Request

curl -X DELETE https://api.example.com/users/123
Send a DELETE request to remove a resource. Common in RESTful API operations.

Example 22PUT Request to Update Data

curl -X PUT -H "Content-Type: application/json" -d '{"name":"Jane"}' https://api.example.com/users/123
Send a PUT request to update an existing resource. PUT is typically used for full resource updates.

Example 23PATCH Request for Partial Update

curl -X PATCH -H "Content-Type: application/json" -d '{"email":"newemail@example.com"}' https://api.example.com/users/123
Send a PATCH request for partial updates. Unlike PUT, PATCH only updates specified fields.

Example 24Download Multiple Files

curl -O https://example.com/file1.pdf -O https://example.com/file2.pdf
Download multiple files in one command by using -O multiple times. Each file is saved with its remote name.

Example 25FTP Download

curl -u username:password ftp://ftp.example.com/file.txt -o file.txt
Download from FTP server with authentication. curl supports many protocols beyond HTTP!

📚 Additional Information

Common curl Options

Option Description
-o, --output Write output to file instead of stdout
-O, --remote-name Save with remote filename
-L, --location Follow redirects
-I, --head Show headers only (HEAD request)
-i, --include Include headers in output
-v, --verbose Verbose output for debugging
-s, --silent Silent mode (no progress)
-S, --show-error Show errors even in silent mode
-X, --request Specify HTTP method (GET, POST, PUT, DELETE, etc.)
-d, --data Send POST data
-H, --header Add custom header
-u, --user Provide username:password for authentication
-A, --user-agent Set User-Agent string
-b, --cookie Send cookies from file or string
-c, --cookie-jar Save cookies to file
-F, --form Upload file (multipart/form-data)
-C, --continue-at Resume download
-#, --progress-bar Show simple progress bar
-w, --write-out Display custom info after transfer
--limit-rate Limit transfer speed
--max-time Maximum time for operation
--retry Retry request on failure
-k, --insecure Skip SSL certificate verification

HTTP Methods (REST API)

Method Purpose Example
GET Retrieve data curl https://api.example.com/users
POST Create new resource curl -X POST -d "data" URL
PUT Update entire resource curl -X PUT -d "data" URL
PATCH Partial update curl -X PATCH -d "data" URL
DELETE Remove resource curl -X DELETE URL
HEAD Get headers only curl -I URL
OPTIONS Check allowed methods curl -X OPTIONS URL

Response Status Codes

# Get just the HTTP status code
curl -o /dev/null -s -w "%{http_code}\n" https://example.com

# Common status codes:
# 200 OK - Success
# 201 Created - Resource created
# 204 No Content - Success, no body
# 301 Moved Permanently - Redirect
# 302 Found - Temporary redirect
# 400 Bad Request - Invalid request
# 401 Unauthorized - Authentication required
# 403 Forbidden - No permission
# 404 Not Found - Resource doesn't exist
# 500 Internal Server Error - Server error
# 503 Service Unavailable - Server down

Advanced curl Techniques

Rate Limiting

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

Timeouts

# Set connection timeout to 10 seconds
curl --connect-timeout 10 https://example.com

# Set maximum time for entire operation to 60 seconds
curl --max-time 60 https://example.com

# Both combined
curl --connect-timeout 10 --max-time 60 https://example.com

Retries

# Retry failed requests up to 5 times
curl --retry 5 https://api.example.com

# Add delay between retries (5 seconds)
curl --retry 5 --retry-delay 5 https://api.example.com

# Retry only on specific errors
curl --retry 3 --retry-connrefused https://api.example.com

Parallel Downloads

# Download multiple files in parallel (curl 7.66+)
curl -Z --parallel --parallel-max 10 \
  -O https://example.com/file1.pdf \
  -O https://example.com/file2.pdf \
  -O https://example.com/file3.pdf

GraphQL Queries

curl -X POST https://api.example.com/graphql \
  -H "Content-Type: application/json" \
  -d '{"query":"{ users { id name email } }"}'

Testing Different HTTP Versions

# Force HTTP/1.1
curl --http1.1 https://example.com

# Force HTTP/2
curl --http2 https://example.com

# Try HTTP/2 but fallback to HTTP/1.1
curl --http2-prior-knowledge https://example.com

Proxy Usage

# Use HTTP proxy
curl -x http://proxy.example.com:8080 https://example.com

# Use SOCKS proxy
curl --socks5 proxy.example.com:1080 https://example.com

# Proxy with authentication
curl -x http://proxy.example.com:8080 -U user:pass https://example.com

Real-World Sysadmin Use Cases

Health Check Monitoring

# Check if service is up
curl -f -s -o /dev/null https://myapp.com/health || echo "Service down!"

# Check multiple endpoints
for url in https://api1.com/health https://api2.com/health; do
  status=$(curl -o /dev/null -s -w "%{http_code}" "$url")
  echo "$url: $status"
done

API Testing in Scripts

#!/bin/bash
# Test API endpoint and parse response
response=$(curl -s -w "\n%{http_code}" https://api.example.com/status)
body=$(echo "$response" | head -n -1)
status=$(echo "$response" | tail -n 1)

if [ "$status" -eq 200 ]; then
  echo "API is healthy: $body"
else
  echo "API error: Status $status"
  exit 1
fi

Download and Verify Checksum

# Download file and its checksum
curl -O https://example.com/file.tar.gz
curl -O https://example.com/file.tar.gz.sha256

# Verify
sha256sum -c file.tar.gz.sha256

Send Alerts to Slack/Discord

# Slack webhook
curl -X POST -H 'Content-type: application/json' \
  --data '{"text":"Server disk space critical!"}' \
  https://hooks.slack.com/services/YOUR/WEBHOOK/URL

# Discord webhook
curl -X POST -H "Content-Type: application/json" \
  -d '{"content":"Backup completed successfully"}' \
  https://discord.com/api/webhooks/YOUR/WEBHOOK

Automated Login and Session

# Login and save session cookie
curl -c cookies.txt -X POST \
  -d "username=admin&password=secret" \
  https://example.com/login

# Use session for authenticated requests
curl -b cookies.txt https://example.com/dashboard

# Logout
curl -b cookies.txt -X POST https://example.com/logout
rm cookies.txt

Check SSL Certificate Expiration

# Get certificate expiration date
curl -vI https://example.com 2>&1 | grep "expire date"

# More detailed certificate info
curl -vI https://example.com 2>&1 | awk '/expire date/{print}'

Download Latest Release from GitHub

# Get latest release URL
latest_url=$(curl -s https://api.github.com/repos/user/repo/releases/latest \
  | grep "browser_download_url.*\.tar\.gz" \
  | cut -d : -f 2,3 \
  | tr -d \")

# Download it
curl -L -O $latest_url

Security Best Practices

  • Avoid plaintext passwords: Use -u username (prompts for password) or environment variables
  • Verify SSL certificates: Don't use -k/--insecure in production
  • Use API tokens: Prefer token authentication over username/password
  • Be careful with -v: Verbose output may expose sensitive data in logs
  • Clear bash history: Use space before command or history -d to remove sensitive commands
  • Store credentials securely: Use .netrc file with proper permissions (600)

Using .netrc for Authentication

# Create ~/.netrc with permissions 600
cat > ~/.netrc << EOF
machine api.example.com
login myusername
password mypassword
EOF

chmod 600 ~/.netrc

# curl will automatically use these credentials
curl https://api.example.com/secure

Debugging Tips

  • Use -v for verbose: See full request/response cycle
  • Use --trace or --trace-ascii: Even more detailed debugging
  • Check DNS resolution: curl -v shows IP address connected to
  • Test with curl -I first: Check headers before downloading large files
  • Use --trace-time: Add timestamps to trace output

curl vs wget

Feature curl wget
Protocols Many (HTTP, FTP, SFTP, SCP, etc.) Fewer (HTTP, HTTPS, FTP)
Recursive download No Yes (wget -r)
API interaction Excellent Basic
POST/PUT/DELETE Easy Difficult
Output to stdout Default Requires -O -
Custom headers Easy (-H) Harder
Best for APIs, single files, automation Mirroring sites, recursive downloads

Performance Optimization

# Use HTTP/2 for better performance
curl --http2 https://example.com

# Enable compression
curl --compressed https://example.com

# Keep-alive (reuse connection for multiple requests)
curl --keepalive-time 60 https://example.com

# Use DNS cache
curl --dns-servers 8.8.8.8 https://example.com

Common Pitfalls and Solutions

Pitfall: Forgetting -L causes curl to not follow redirects
Solution: Always use -L when dealing with URLs that might redirect
Pitfall: Using single quotes with JSON in Windows breaks
Solution: Windows PowerShell requires double quotes; escape inner quotes
Pitfall: Large downloads timeout
Solution: Use --max-time or --connect-timeout appropriately

Quick Reference Commands

# Simple GET
curl https://example.com

# GET with headers shown
curl -i https://example.com

# POST with JSON
curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' URL

# POST with form data
curl -X POST -d "key=value" URL

# Upload file
curl -F "file=@path/to/file" URL

# Download with progress bar
curl -# -O URL

# Follow redirects
curl -L URL

# Save to file
curl -o filename URL

# Silent but show errors
curl -sS URL

# With authentication
curl -u user:pass URL

# With custom header
curl -H "Authorization: Bearer TOKEN" URL

# Timing information
curl -w "%{time_total}\n" -o /dev/null -s URL

# Just status code
curl -o /dev/null -s -w "%{http_code}\n" URL
Pro Tip for Beginners: Start with simple GET requests (curl URL), then gradually add options as you need them. The man page (man curl) is excellent and has examples for almost everything.
Pro Tip for Sysadmins: Create shell functions for common curl patterns you use frequently. For example, a function for checking API health, another for posting to Slack, etc.

Useful Shell Functions

# Check HTTP status
http_status() {
  curl -o /dev/null -s -w "%{http_code}\n" "$1"
}

# Pretty print JSON response
curl_json() {
  curl -s "$1" | jq .
}

# Download with retry and resume
curl_reliable() {
  curl -C - --retry 5 --retry-delay 3 -# -O "$1"
}

# Usage:
# http_status https://google.com
# curl_json https://api.github.com/users/octocat
# curl_reliable https://example.com/largefile.zip

Testing APIs: Complete Workflow

# 1. Check if API is reachable
curl -I https://api.example.com

# 2. Test authentication
curl -H "Authorization: Bearer YOUR_TOKEN" https://api.example.com/auth/test

# 3. GET request
curl -H "Authorization: Bearer YOUR_TOKEN" https://api.example.com/users

# 4. POST request (create)
curl -X POST \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"John","email":"john@example.com"}' \
  https://api.example.com/users

# 5. PUT request (update)
curl -X PUT \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"John Updated"}' \
  https://api.example.com/users/123

# 6. DELETE request
curl -X DELETE \
  -H "Authorization: Bearer YOUR_TOKEN" \
  https://api.example.com/users/123

Fun Facts

  • curl was first released in 1997 as httpget, then renamed to curl
  • The creator, Daniel Stenberg, still maintains curl after 25+ years
  • curl is used in virtually every connected device - cars, TVs, phones, spacecraft
  • NASA used curl on the Mars helicopter Ingenuity
  • curl supports over 25 different protocols
  • The official curl website uses curl in its logo: curl.se
  • There's a "curl up" conference dedicated to curl and HTTP