cURL — The Tool Every Administrator Needs
A practical cURL guide for system administrators. Test APIs, DNS, HTTPS, certificates, authentication, proxies, redirects, webhooks, downloads, performance and network connectivity directly from the command line.
Scope
A practical cURL guide for system administrators. Test APIs, DNS, HTTPS, certificates, authentication, proxies, redirects, webhooks, downloads, performance and network connectivity directly from the command line.
Every system administrator has a collection of tools they reach for when something breaks.
ping.
traceroute.
nslookup.
dig.
openssl.
telnet.
nc.
And one tool that is often underestimated:
curl
Many people know cURL as something that downloads a webpage:
curl https://example.com
But for an administrator, cURL is much more useful than that.
It can answer questions such as:
- Is the web server actually responding?
- Is DNS pointing to the correct server?
- Does HTTPS work?
- Which certificate is being presented?
- Is the reverse proxy redirecting requests correctly?
- Does the API accept my token?
- Is the backend reachable even if DNS is broken?
- Does IPv6 work?
- Is the problem in the browser or on the server?
- Does the webhook actually receive requests?
- How long does DNS, TCP, TLS and server processing take?
- Does the application work through the corporate proxy?
- Does a virtual host respond correctly before DNS is changed?
And it can usually answer those questions with a single command.
If you administer servers, networks, cloud services, APIs, firewalls, containers or web applications, cURL belongs in your troubleshooting toolbox.
What is cURL?
cURL stands for Client URL.
It is a command-line tool for transferring data using URLs.
Most administrators primarily use it with:
HTTP
HTTPS
But depending on how cURL was compiled, it can also support protocols such as:
FTP
FTPS
SFTP
SCP
SMTP
IMAP
POP3
LDAP
SMB
You can see what your installation supports with:
curl --version
Example:
curl 8.x.x
Protocols:
file ftp ftps http https imap imaps ipfs ipns mqtt pop3
pop3s smtp smtps telnet tftp
The exact list depends on the operating system and cURL build.
First command every administrator should know
The simplest request is:
curl https://example.com
cURL connects to the server and prints the response body.
For a website that usually means HTML:
<!doctype html>
<html>
<head>
<title>Example Domain</title>
</head>
...
That alone already proves several things worked:
DNS resolution
↓
TCP connection
↓
TLS negotiation
↓
HTTP request
↓
HTTP response
Your browser performs the same basic sequence.
cURL simply lets you see it without the browser hiding everything behind a graphical interface.
1. Check whether a website responds
Probably the most basic administrator test:
curl https://example.com
But normally you don't care about the entire HTML page.
You want to know whether the server responds.
Use:
curl -I https://example.com
-I requests only the HTTP headers.
Example:
HTTP/2 200
content-type: text/html
content-length: 1256
server: nginx
date: Wed, 16 Sep 2026 08:14:22 GMT
The important part is:
HTTP/2 200
The web server is responding successfully.
Common HTTP status codes
When troubleshooting, the status code immediately tells you something.
200 OK
The request succeeded.
301 Moved Permanently
302 Found
307 Temporary Redirect
308 Permanent Redirect
The server is redirecting the request.
400 Bad Request
The request is malformed.
401 Unauthorized
Authentication is required or invalid.
403 Forbidden
The server understood the request but refuses access.
404 Not Found
The resource does not exist.
429 Too Many Requests
You have probably hit a rate limit.
500 Internal Server Error
The application failed.
502 Bad Gateway
A reverse proxy could not communicate correctly with the backend.
503 Service Unavailable
The application is unavailable.
504 Gateway Timeout
The proxy waited for the backend and timed out.
Already, cURL can tell you much more than:
"The website doesn't work."
2. Follow redirects
Consider:
curl -I http://example.com
You may receive:
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
cURL does not follow redirects automatically in many normal requests.
Use:
curl -L http://example.com
-L means:
follow Location headers
For troubleshooting, combine it with headers:
curl -IL http://example.com
You might see:
HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/
HTTP/2 200
content-type: text/html
This makes redirect loops and incorrect HTTP-to-HTTPS redirects much easier to find.
3. See exactly what cURL is doing
One of the most useful options in the entire tool is:
curl -v https://example.com
-v means verbose.
The output might include:
* Host example.com:443 was resolved.
* IPv4: 93.184.216.34
* Connected to example.com
* TLSv1.3 connection established
* Server certificate:
* subject: CN=example.com
* issuer: Let's Encrypt
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/8.x
>
< HTTP/1.1 200 OK
< Server: nginx
< Content-Type: text/html
Now you can see:
DNS
IP address
TCP connection
TLS
Certificate
HTTP request
HTTP response
Headers
When something mysterious happens, try:
curl -v
before opening ten other tools.
4. Test DNS and the web server separately
Suppose:
portal.example.com
does not work.
You know the server should be:
192.0.2.50
DNS might be wrong.
One extremely useful cURL feature is:
--resolve
Example:
curl --resolve portal.example.com:443:192.0.2.50 https://portal.example.com
This tells cURL:
For this request only:
portal.example.com
↓
192.0.2.50
without changing DNS.
This is incredibly useful.
Why --resolve is better than testing the IP directly
You might think you can simply do:
curl https://192.0.2.50
But HTTPS virtual hosting relies on the hostname.
The server may host:
portal.example.com
api.example.com
www.example.com
mail.example.com
on the same IP address.
HTTPS also uses SNI to identify the requested hostname.
Therefore:
curl --resolve portal.example.com:443:192.0.2.50 \
https://portal.example.com
tests the server properly.
It preserves:
hostname
Host header
TLS SNI
certificate validation
while bypassing DNS.
This is one of the most useful cURL commands for web administrators.
5. Test a new server before changing DNS
Imagine you are migrating:
www.company.com
Old server:
192.0.2.10
New server:
192.0.2.20
DNS still points to the old server.
You can test the new server with:
curl --resolve www.company.com:443:192.0.2.20 \
https://www.company.com
If everything works, you know the new server can correctly serve the production hostname before touching DNS.
You can also inspect the headers:
curl -I \
--resolve www.company.com:443:192.0.2.20 \
https://www.company.com
Or use verbose mode:
curl -v \
--resolve www.company.com:443:192.0.2.20 \
https://www.company.com
This should be part of almost every web migration checklist.
6. Test a virtual host manually
Sometimes you need to test HTTP without TLS:
curl http://192.0.2.50 \
-H "Host: portal.example.com"
This sends:
Host: portal.example.com
even though you connected directly to:
192.0.2.50
Useful for testing:
Apache VirtualHost
nginx server_name
reverse proxies
load balancers
internal web applications
For HTTPS, however, prefer --resolve because it handles SNI correctly as well.
7. Inspect HTTP headers
Headers often reveal what infrastructure is actually processing the request.
Run:
curl -I https://example.com
Possible response:
HTTP/2 200
server: cloudflare
content-type: text/html
cache-control: max-age=3600
cf-cache-status: HIT
strict-transport-security: max-age=31536000
From this alone you may discover:
Cloudflare is in front of the application
The response was cached
HSTS is enabled
The content type is HTML
You can display response headers together with the body using:
curl -i https://example.com
Difference:
-I
headers only.
-i
headers + body.
8. Save headers separately
Useful when debugging API calls:
curl -D headers.txt https://example.com
The response body goes to the terminal while the headers are saved to:
headers.txt
Or:
curl -D headers.txt \
-o response.html \
https://example.com
Now you have:
headers.txt
response.html
for analysis.
9. Send custom HTTP headers
Almost every API administrator eventually needs:
-H
Example:
curl https://api.example.com/status \
-H "Accept: application/json"
Multiple headers:
curl https://api.example.com/status \
-H "Accept: application/json" \
-H "X-Client-ID: admin-tool"
You can test web applications with custom headers as well.
Example:
curl https://example.com \
-H "X-Forwarded-For: 192.0.2.100"
Useful when testing reverse proxy logic.
10. Change the User-Agent
Some applications behave differently depending on the client.
Default cURL user-agent might look like:
curl/8.x.x
Change it with:
curl https://example.com \
-A "Mozilla/5.0"
Or:
curl https://example.com \
-H "User-Agent: Monitoring-System"
This can help diagnose applications or security systems that treat browsers, bots and monitoring agents differently.
11. Test REST APIs
This is where cURL becomes indispensable.
Suppose an API endpoint is:
https://api.example.com/v1/servers
A GET request:
curl https://api.example.com/v1/servers
You might receive:
{
"servers": [
{
"name": "WEB01",
"status": "online"
},
{
"name": "SQL01",
"status": "online"
}
]
}
No Postman.
No browser extension.
No custom script.
One command.
12. Pretty-print JSON with jq
Raw JSON can be difficult to read.
Combine cURL with jq:
curl -s https://api.example.com/v1/servers | jq
Instead of:
{"servers":[{"name":"WEB01","status":"online"}]}
you get:
{
"servers": [
{
"name": "WEB01",
"status": "online"
}
]
}
You can also extract specific values:
curl -s https://api.example.com/v1/servers \
| jq '.servers[].name'
Result:
"WEB01"
"SQL01"
curl + jq is one of the most useful combinations in Linux administration.
13. Bearer token authentication
Many modern APIs use OAuth or bearer tokens.
Example:
curl https://api.example.com/v1/users \
-H "Authorization: Bearer YOUR_TOKEN"
Equivalent HTTP request:
Authorization: Bearer YOUR_TOKEN
For example:
curl https://api.github.com/user \
-H "Authorization: Bearer YOUR_TOKEN"
Never publish real tokens in documentation, ticket systems or screenshots.
14. API key authentication
Some APIs use custom headers.
For example:
curl https://api.example.com/data \
-H "X-API-Key: YOUR_API_KEY"
Or:
curl https://api.example.com/data \
-H "Authorization: ApiKey YOUR_API_KEY"
The exact header depends on the API.
Security warning: command history
This works:
curl https://api.example.com \
-H "Authorization: Bearer super-secret-token"
But the token may end up in:
shell history
process listings
terminal logs
screen recordings
support transcripts
For sensitive automation, use environment variables or protected credential mechanisms.
Example:
export API_TOKEN="super-secret-token"
Then:
curl https://api.example.com \
-H "Authorization: Bearer $API_TOKEN"
Still understand the security characteristics of your operating system and shell.
Do not treat the command line as a secret vault.
15. Basic authentication
Older APIs and management interfaces may use HTTP Basic Authentication.
Example:
curl -u admin https://server.example.com/api
cURL asks for the password.
You can technically provide both:
curl -u admin:password https://server.example.com/api
But this is usually a bad idea because the password may become visible in shell history or process information.
Prefer:
curl -u admin https://server.example.com/api
and enter the password interactively.
16. Send a POST request
POST requests are common with APIs.
Example:
curl -X POST https://api.example.com/v1/restart
But usually you need to send data.
17. POST JSON data
Example API expects:
{
"hostname": "WEB01",
"action": "restart"
}
Use:
curl https://api.example.com/v1/actions \
-X POST \
-H "Content-Type: application/json" \
-d '{"hostname":"WEB01","action":"restart"}'
This is one of the most common cURL API patterns.
Better: send JSON from a file
Create:
request.json
containing:
{
"hostname": "WEB01",
"action": "restart"
}
Then:
curl https://api.example.com/v1/actions \
-H "Content-Type: application/json" \
-d @request.json
Much cleaner for larger requests.
Modern cURL versions also support:
curl https://api.example.com/v1/actions \
--json @request.json
which is especially convenient for JSON APIs.
18. PUT requests
PUT is commonly used to replace or update a resource.
Example:
curl -X PUT \
https://api.example.com/v1/servers/WEB01 \
-H "Content-Type: application/json" \
-d '{"maintenance":true}'
19. PATCH requests
PATCH usually modifies part of an existing resource.
Example:
curl -X PATCH \
https://api.example.com/v1/users/100 \
-H "Content-Type: application/json" \
-d '{"enabled":false}'
For an administrator, this might represent:
disable account
change configuration
update object
modify firewall rule
change ticket status
Be careful.
A successful cURL command can be just as destructive as a successful PowerShell command.
20. DELETE requests
Delete an API object:
curl -X DELETE \
https://api.example.com/v1/users/100
With authentication:
curl -X DELETE \
https://api.example.com/v1/users/100 \
-H "Authorization: Bearer $API_TOKEN"
If you are testing against production, verify the endpoint before pressing Enter.
curl does exactly what you ask it to do.
21. Submit HTML form data
Traditional websites often expect:
application/x-www-form-urlencoded
Example:
curl https://example.com/login \
-d "username=admin" \
-d "password=test"
This produces form-style data similar to:
username=admin&password=test
Again, do not use real production passwords directly in command history.
22. Upload a file
Suppose an API accepts a configuration backup.
Use:
curl https://api.example.com/upload \
-F "file=@backup.zip"
Additional form data:
curl https://api.example.com/upload \
-F "file=@backup.zip" \
-F "device=router01"
This sends a multipart form upload similar to what a browser would generate.
23. Download a file
Basic example:
curl https://example.com/file.zip \
-o file.zip
-o specifies the output filename.
Preserve the server filename
Use:
curl -O https://example.com/files/backup.zip
The file will be saved as:
backup.zip
Follow redirects when downloading
Many download links redirect to CDNs.
Use:
curl -L \
-O https://example.com/download/latest
Without -L, you may only download the redirect response.
24. Resume an interrupted download
Suppose a 10 GB file stopped at 7 GB.
Instead of starting again:
curl -C - \
-O https://example.com/large-backup.tar.gz
-C - tells cURL to resume from the existing file position if supported by the server.
Very useful for:
ISO images
backup files
firmware
large logs
VM images
25. Limit download speed
Sometimes you are testing a production connection and don't want to saturate it.
Example:
curl --limit-rate 2M \
-O https://example.com/large-file.iso
The transfer is limited to approximately:
2 MB/s
Useful when working across slow WAN or VPN links.
26. Test a webhook
Suppose n8n exposes:
https://automation.example.com/webhook/test
Test it with:
curl -X POST \
https://automation.example.com/webhook/test
Send JSON:
curl -X POST \
https://automation.example.com/webhook/test \
-H "Content-Type: application/json" \
-d '{
"server": "SQL01",
"severity": "critical",
"message": "Database unavailable"
}'
This is extremely useful when building:
n8n workflows
monitoring integrations
Slack integrations
Teams integrations
GitHub webhooks
custom APIs
alerting systems
Instead of waiting for the real system to generate an event, generate one yourself.
27. Test monitoring integrations
Imagine Zabbix normally sends this payload:
{
"host": "SQL01",
"problem": "Database unavailable",
"severity": 5
}
You can simulate it:
curl https://automation.example.com/webhook/zabbix \
-X POST \
-H "Content-Type: application/json" \
-d '{
"host":"SQL01",
"problem":"Database unavailable",
"severity":5
}'
Now you can test the complete workflow without deliberately breaking SQL01.
Much safer.
28. Check TLS certificates
Verbose mode displays certificate information:
curl -v https://example.com
Look for lines similar to:
SSL connection using TLSv1.3
Server certificate:
subject: CN=example.com
issuer: Let's Encrypt
For detailed certificate inspection, openssl s_client is often the better specialized tool.
But cURL is excellent for answering the practical question:
Can an actual HTTPS client successfully connect and validate this certificate?
29. Test an invalid certificate
Suppose an internal server uses a self-signed certificate.
Running:
curl https://internal.example.local
may produce:
curl: (60) SSL certificate problem
You can temporarily bypass certificate validation with:
curl -k https://internal.example.local
or:
curl --insecure https://internal.example.local
But understand what you just did.
You disabled certificate verification.
Never use -k as the permanent fix
This:
curl -k
does not repair TLS.
It simply says:
I don't care whether I can trust this server.
Useful for troubleshooting?
Yes.
Correct production solution?
Usually no.
Instead fix:
certificate trust
hostname mismatch
certificate chain
internal CA
expired certificate
The amount of infrastructure permanently running with certificate verification disabled because somebody once said "just add -k" is terrifying.
30. Use a custom CA certificate
For internal PKI:
curl https://internal.example.com \
--cacert company-root-ca.pem
Now cURL validates the server using your CA.
This is a much better solution than:
-k
31. Test mutual TLS / client certificates
Some administrative APIs require client certificate authentication.
Example:
curl https://secure-api.example.com \
--cert client.crt \
--key client.key
If the private key is protected with a password, cURL can request or accept the required credentials depending on the certificate format and configuration.
Typical use cases:
internal PKI
banking APIs
machine-to-machine authentication
enterprise APIs
high-security management interfaces
32. Use a PFX/P12 certificate
Administrators often receive:
client.pfx
or:
client.p12
Depending on the cURL/TLS backend and environment, PKCS#12 certificates can be used directly.
For example:
curl https://secure.example.com \
--cert-type P12 \
--cert client.p12
The exact behavior may depend on how cURL was built, especially on Windows.
33. Test a proxy
Suppose your organization uses:
proxy.example.com:8080
Test HTTP through it:
curl https://example.com \
-x http://proxy.example.com:8080
With authentication:
curl https://example.com \
-x http://proxy.example.com:8080 \
-U username
cURL can then ask for the proxy password instead of exposing it directly.
Useful for diagnosing:
corporate proxy
security gateway
web filtering
application connectivity
internet access from servers
34. Test SOCKS proxy connections
For SOCKS5:
curl \
--socks5 127.0.0.1:1080 \
https://example.com
If you want hostname resolution to happen through the SOCKS proxy as well:
curl \
--socks5-hostname 127.0.0.1:1080 \
https://example.com
The distinction matters when diagnosing DNS leaks or remote networks.
35. Test cookies
Receive cookies and save them:
curl https://example.com/login \
-c cookies.txt
Reuse them:
curl https://example.com/account \
-b cookies.txt
You can combine both:
curl \
-b cookies.txt \
-c cookies.txt \
https://example.com/account
Very useful for testing:
sessions
authentication flows
load balancers
application gateways
SSO debugging
36. Test redirects and cookies together
Some login systems perform multiple redirects:
/login
↓
SSO provider
↓
callback
↓
application
A useful test:
curl -L \
-c cookies.txt \
-b cookies.txt \
https://portal.example.com
Add verbose mode when troubleshooting:
curl -vL \
-c cookies.txt \
-b cookies.txt \
https://portal.example.com
Now you can watch the entire HTTP flow.
37. Force IPv4
A classic problem:
Website works for some users.
Website times out for others.
One possible cause is broken IPv6.
Test IPv4:
curl -4 https://example.com
Then IPv6:
curl -6 https://example.com
If:
curl -4
works instantly but:
curl -6
fails, you have learned something extremely important.
Possible problem areas:
AAAA DNS record
IPv6 routing
firewall
reverse proxy
load balancer
server IPv6 configuration
This simple test can save hours.
38. Test HTTP/1.1
Force HTTP/1.1:
curl --http1.1 https://example.com
Useful when investigating:
reverse proxy issues
legacy applications
HTTP/2 problems
load balancer behaviour
39. Test HTTP/2
Force HTTP/2 where supported:
curl --http2 https://example.com
You can compare:
curl --http1.1 https://example.com
against:
curl --http2 https://example.com
to determine whether a problem is protocol-specific.
Your cURL build must support HTTP/2.
Check:
curl --version
40. Test compressed responses
Browsers usually support compression.
Test that behaviour with:
curl --compressed https://example.com
This tells the server cURL supports compression such as gzip or Brotli where available and supported.
Useful when troubleshooting:
compression
CDNs
reverse proxies
Content-Encoding
corrupt compressed responses
41. Add timeouts
Never let automated scripts wait forever.
Set a connection timeout:
curl \
--connect-timeout 5 \
https://example.com
Meaning:
Give up if connection establishment takes more than 5 seconds.
Set a maximum total duration:
curl \
--max-time 20 \
https://example.com
Combined:
curl \
--connect-timeout 5 \
--max-time 20 \
https://example.com
Very useful in automation and monitoring scripts.
42. Retry failed connections
For unreliable endpoints:
curl \
--retry 3 \
https://api.example.com
You can also add delay:
curl \
--retry 3 \
--retry-delay 5 \
https://api.example.com
Meaning roughly:
Try
↓
fail
↓
wait 5 seconds
↓
try again
Useful for:
temporary network failures
API availability
downloads
automated jobs
Don't use infinite retries to hide real infrastructure problems.
43. Check only whether an endpoint works
Sometimes you don't need the response body.
Use:
curl -s \
-o /dev/null \
-w "%{http_code}\n" \
https://example.com
Result:
200
This is excellent for scripts.
Example:
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://example.com)
Then:
if [ "$STATUS" = "200" ]; then
echo "Website OK"
else
echo "Website failed: $STATUS"
fi
Congratulations.
You just created a tiny HTTP monitoring system.
44. Measure website performance
cURL can report detailed timing information.
Example:
curl -s \
-o /dev/null \
-w 'DNS: %{time_namelookup}\nConnect: %{time_connect}\nTLS: %{time_appconnect}\nTTFB: %{time_starttransfer}\nTotal: %{time_total}\n' \
https://example.com
Example output:
DNS: 0.012
Connect: 0.028
TLS: 0.091
TTFB: 0.244
Total: 0.251
Now you have something much more useful than:
The website feels slow.
Understanding those timings
DNS
time_namelookup
How long DNS resolution took.
If this is slow:
check DNS
resolver
network
DNS forwarding
TCP connection
time_connect
How long until the TCP connection was established.
If this is slow:
routing
firewall
server load
WAN latency
packet loss
may be involved.
TLS
time_appconnect
How long it took to establish HTTPS/TLS.
If this is unusually slow:
TLS handshake
network latency
certificate infrastructure
proxy
security inspection
may deserve investigation.
Time to first byte
time_starttransfer
Often called TTFB.
This is extremely useful.
If:
DNS = 0.01 s
TCP = 0.02 s
TLS = 0.08 s
TTFB = 4.8 s
the network probably isn't your main problem.
The application spent several seconds before sending a response.
Look at:
database
application
backend API
PHP
Java
.NET
WordPress
storage
instead of blaming the network.
Total time
time_total
Total request duration.
45. Build a reusable performance test
Create:
curl -s -o /dev/null \
-w '\
HTTP: %{http_code}\n\
DNS: %{time_namelookup}s\n\
TCP: %{time_connect}s\n\
TLS: %{time_appconnect}s\n\
TTFB: %{time_starttransfer}s\n\
TOTAL: %{time_total}s\n' \
https://example.com
Output:
HTTP: 200
DNS: 0.006s
TCP: 0.021s
TLS: 0.075s
TTFB: 0.143s
TOTAL: 0.146s
This command belongs in every administrator's notes.
46. Check the remote IP
You can make cURL report where it actually connected:
curl -s \
-o /dev/null \
-w "Remote IP: %{remote_ip}\n" \
https://example.com
Result:
Remote IP: 203.0.113.24
Useful when dealing with:
CDNs
DNS round robin
load balancers
Cloudflare
multiple web servers
47. Check your public IP address
One of the most common administrator commands:
curl https://api.ipify.org
or another trusted IP-checking service.
Result:
203.0.113.50
Useful when testing:
NAT
VPN
WireGuard
proxy
firewall routing
policy routing
multiple WAN connections
For example:
Before VPN:
curl https://api.ipify.org
Result:
80.x.x.x
After VPN:
curl https://api.ipify.org
Result:
91.x.x.x
Now you know whether Internet traffic actually exits through the tunnel.
48. Select a network interface
A server may have multiple network interfaces.
For example:
eth0 — production
eth1 — management
wg0 — WireGuard
You can tell cURL which one to use:
curl \
--interface eth1 \
https://example.com
Or sometimes a source IP:
curl \
--interface 192.0.2.10 \
https://example.com
Very useful when troubleshooting:
multi-WAN
VPN
policy routing
multiple VLAN interfaces
multiple NICs
49. Test a service on a custom port
Example:
curl http://server.example.com:8080
HTTPS:
curl https://server.example.com:8443
Verbose:
curl -v https://server.example.com:8443
Useful for:
Tomcat
Kubernetes services
Docker applications
management interfaces
reverse proxies
development servers
50. Test a Docker application locally
Suppose Docker exposes:
127.0.0.1:5678
Test:
curl http://127.0.0.1:5678
If that works but:
curl https://automation.example.com
doesn't, the application may be healthy.
The problem could instead be:
nginx
Apache
Traefik
DNS
TLS
firewall
reverse proxy configuration
This allows you to isolate layers.
51. Test reverse proxy versus backend
Imagine:
Internet
↓
nginx
↓
Application :8080
Test backend:
curl http://127.0.0.1:8080
Then proxy:
curl https://app.example.com
If backend works but proxy fails:
application = probably OK
reverse proxy / TLS / DNS = investigate
This basic methodology solves an enormous number of web infrastructure problems.
52. Test an API health endpoint
Well-designed applications often expose:
/health
/healthz
/status
/api/health
Example:
curl https://api.example.com/health
Response:
{
"status": "healthy",
"database": "connected",
"redis": "connected"
}
For automation:
curl -f https://api.example.com/health
-f causes HTTP errors to return a failure exit code.
That is extremely useful in scripts.
53. Use cURL exit codes in scripts
Example:
if curl -fsS https://example.com/health > /dev/null; then
echo "Service is healthy"
else
echo "Service failed"
fi
Here:
-f = fail on HTTP errors
-s = silent
-S = still show errors
The combination:
-fsS
is very popular in administrator scripts.
54. Silent mode
Normal cURL shows a progress meter.
Remove it:
curl -s https://example.com
Useful when piping output:
curl -s https://api.example.com | jq
But silent mode also hides error messages.
Therefore scripts often use:
curl -sS
Meaning:
be quiet normally
but show actual errors
55. Download only part of a file
HTTP supports byte ranges.
For example:
curl \
-r 0-1023 \
https://example.com/large-file.bin
Downloads only the first:
1024 bytes
Useful for testing whether a server supports range requests without downloading a huge file.
56. Inspect CDN and cache behaviour
Run:
curl -I https://example.com
Look for headers such as:
Age
Cache-Control
CF-Cache-Status
X-Cache
Via
ETag
Last-Modified
Example:
CF-Cache-Status: HIT
Age: 841
Then repeat the request.
This helps determine whether you are seeing:
cached response
origin response
stale content
CDN issue
57. Bypass DNS cache during server migration
Suppose DNS has already changed but your local resolver still has the old IP.
Instead of waiting:
curl \
--resolve example.com:443:NEW_IP \
https://example.com
You immediately test the new destination.
Again, no need to edit:
/etc/hosts
C:\Windows\System32\drivers\etc\hosts
and forget to remove the change later.
58. Test an API from the same network as the application
This is an important troubleshooting principle.
Suppose users say:
Application cannot reach API.
Running cURL from your laptop proves almost nothing.
SSH to the application server and run:
curl -v https://api.example.com
from there.
Now you are testing:
same source network
same DNS
same firewall rules
same proxy
same routing
same TLS environment
Always test as close as possible to the failing application.
59. Test connectivity from inside a container
If an application runs in Docker:
docker exec -it container-name sh
Then, if cURL exists:
curl -v https://api.example.com
This can reveal problems with:
container DNS
Docker network
proxy environment
firewall
routing
CA trust
The host working does not automatically mean the container works.
60. Test Kubernetes connectivity
The same principle applies to Kubernetes.
From a pod:
curl http://service-name:8080/health
Or launch a temporary debugging container if your environment allows it.
Now you can determine whether:
DNS
Service
NetworkPolicy
Ingress
application
is responsible.
61. Debug authentication redirects
Suppose accessing:
https://portal.example.com
returns unexpected login behaviour.
Run:
curl -vI https://portal.example.com
You might see:
HTTP/2 302
location: https://login.microsoftonline.com/...
Now you know the application is intentionally redirecting to the identity provider.
Continue following it with:
curl -vIL https://portal.example.com
This can reveal badly configured:
callback URLs
reverse proxy headers
HTTP/HTTPS redirects
SSO paths
62. Test the Host header behind a load balancer
Suppose a backend server hosts several applications.
Directly connect to the backend:
curl http://10.0.0.20 \
-H "Host: app.example.com"
If this works but the load-balanced URL fails:
backend is likely healthy
investigate load balancer / proxy
Again, isolate layers instead of guessing.
63. Identify server software
Sometimes headers reveal the server:
curl -I https://example.com
Possible output:
Server: nginx
or:
Server: Apache
or:
Server: Microsoft-IIS/10.0
Do not assume this is always accurate.
Reverse proxies can hide or modify headers.
But it can still provide useful diagnostic information.
64. Test rate limiting
Suppose an API occasionally returns:
429 Too Many Requests
Inspect headers:
curl -i https://api.example.com
You may see something such as:
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
Now you know the failure isn't random.
You are hitting an API rate limit.
65. Send a Referer header
Some applications or security systems inspect the HTTP Referer.
Example:
curl https://example.com/download \
-e "https://example.com/"
Equivalent:
curl https://example.com/download \
-H "Referer: https://example.com/"
Useful when reproducing application behaviour.
66. Send a HEAD request
HEAD asks for the headers without the response body.
Use:
curl -I https://example.com/file.iso
You may receive:
HTTP/2 200
content-type: application/octet-stream
content-length: 5872447488
Now you know the file exists and its size without downloading 5 GB.
67. Check whether a download server supports ranges
Run:
curl -I https://example.com/file.iso
Look for:
Accept-Ranges: bytes
This usually indicates resume/range support.
Useful when dealing with large downloads.
68. Troubleshoot certificate hostname problems
Suppose:
curl https://server.example.com
returns a certificate error.
Try verbose mode:
curl -v https://server.example.com
Check whether the certificate was issued for:
server.example.com
and not:
server.internal
oldserver.example.com
*.different-domain.com
Common causes:
wrong virtual host
wrong reverse proxy certificate
old certificate
DNS pointing to wrong server
load balancer misconfiguration
69. Compare public and internal DNS results indirectly
Suppose internal users and Internet users reach different systems.
From inside the network:
curl -v https://portal.example.com
Observe:
Trying 10.0.0.20...
From outside:
Trying 203.0.113.20...
You may be dealing with:
split DNS
split-horizon DNS
internal reverse proxy
different infrastructure paths
This can explain the classic:
It works internally but not externally.
70. Test SMTP with cURL
cURL can do more than HTTP.
If your build supports SMTP, you can test SMTP connectivity.
For example:
curl -v smtp://mail.example.com:25
This can show whether the server responds.
For TLS:
curl -v \
--ssl-reqd \
smtp://mail.example.com:587
Authenticated mail submission can also be tested, but be very careful with credentials and avoid sending unauthorized mail.
For deep SMTP diagnostics, specialized tools such as openssl s_client or SMTP-specific test utilities may provide more visibility.
Still, cURL can be surprisingly useful.
71. Test FTP
If you still have legacy FTP infrastructure:
curl ftp://ftp.example.com/
With authentication:
curl -u username \
ftp://ftp.example.com/
Download:
curl -u username \
ftp://ftp.example.com/file.txt \
-o file.txt
Yes, FTP still exists.
Unfortunately.
72. Use cURL in automation
Consider a backup monitoring script.
Check API:
curl -fsS \
https://backup.example.com/api/status \
-H "Authorization: Bearer $BACKUP_TOKEN"
Pipe to jq:
curl -fsS \
https://backup.example.com/api/status \
-H "Authorization: Bearer $BACKUP_TOKEN" \
| jq '.failedJobs'
Result:
2
Now:
FAILED=$(curl -fsS \
https://backup.example.com/api/status \
-H "Authorization: Bearer $BACKUP_TOKEN" \
| jq '.failedJobs')
Then:
if [ "$FAILED" -gt 0 ]; then
echo "Backup failures detected: $FAILED"
fi
You just created an API integration with almost no code.
73. cURL as part of monitoring
A monitoring system can use:
curl -fsS https://application.example.com/health
If the command returns:
exit code 0
service is healthy.
If it returns non-zero:
alert
This can be integrated into:
Zabbix
Nagios
Icinga
cron
systemd timers
shell scripts
CI/CD pipelines
Docker health checks
74. Docker health check example
A container may define:
HEALTHCHECK CMD curl -f http://localhost:8080/health || exit 1
Now Docker can determine whether the application inside the container is actually responding.
Not merely whether the process exists.
There is an important difference between:
process running
and:
application working
75. CI/CD deployment verification
After deployment:
curl -fsS \
https://app.example.com/health
If that fails:
deployment = failed
A deployment pipeline could check:
curl -fsS https://app.example.com/health > /dev/null
and stop before promoting a broken version.
76. Useful cURL error codes
cURL often gives a numeric error.
Learn a few common ones.
Error 6
curl: (6) Could not resolve host
Usually:
DNS problem
invalid hostname
resolver unavailable
Error 7
curl: (7) Failed to connect
Possible causes:
service not listening
firewall
wrong port
routing
server offline
Error 28
curl: (28) Operation timed out
Possible causes:
network timeout
server hanging
firewall silently dropping
slow backend
Error 35
curl: (35) SSL connect error
Investigate:
TLS versions
cipher compatibility
proxy
TLS inspection
server configuration
Error 60
curl: (60) SSL certificate problem
Usually related to:
certificate trust
CA chain
self-signed certificate
hostname/certificate validation
Do not immediately solve it with:
-k
Understand why validation failed first.
77. Windows administrators: use curl.exe
Modern Windows versions include cURL.
Test:
curl.exe --version
On some PowerShell environments, especially older ones, the command:
curl
may historically have been associated with PowerShell's:
Invoke-WebRequest
rather than the native cURL binary.
When you specifically want real cURL on Windows, use:
curl.exe
Example:
curl.exe -I https://example.com
This also makes scripts more explicit.
78. macOS
cURL is normally available directly:
curl --version
Use:
curl -v https://example.com
No additional installation is usually required for normal use.
79. Linux
Most Linux distributions either include cURL or make it immediately available through the package manager.
Check:
curl --version
If missing, install it using your distribution's package management system.
For Debian/Ubuntu, typically:
sudo apt install curl
For Fedora-family systems:
sudo dnf install curl
80. A real troubleshooting example
User reports:
https://app.example.com doesn't work.
Do not immediately restart the server.
Start systematically.
Step 1 — Test response
curl -I https://app.example.com
Result:
HTTP/2 502
We now know:
DNS works
TCP works
HTTPS works
reverse proxy responds
backend probably does not
That is already significant.
Step 2 — Check verbose output
curl -v https://app.example.com
TLS is fine.
Step 3 — Test backend directly
SSH to the reverse proxy:
curl http://127.0.0.1:8080
Result:
Connection refused
Now we know where to look.
Not DNS.
Not TLS.
Not the firewall.
Not the browser.
The backend application isn't listening.
This is how administrators should troubleshoot.
Eliminate layers one by one.
Another example: website works internally but not externally
Internal test:
curl -v https://portal.example.com
Shows:
Connected to 10.1.10.20
HTTP/2 200
External test shows:
Connected to 203.0.113.20
HTTP/2 502
Now you know:
internal DNS path = working
external path = broken
Investigate:
public DNS
NAT
reverse proxy
load balancer
firewall
instead of touching the application server.
Another example: website is "slow"
Run:
curl -s -o /dev/null \
-w '\
DNS: %{time_namelookup}s\n\
TCP: %{time_connect}s\n\
TLS: %{time_appconnect}s\n\
TTFB: %{time_starttransfer}s\n\
TOTAL: %{time_total}s\n' \
https://app.example.com
Result:
DNS: 0.011s
TCP: 0.024s
TLS: 0.081s
TTFB: 6.421s
TOTAL: 6.430s
Stop debugging DNS.
Stop blaming the firewall.
The application took more than six seconds before returning the first byte.
Investigate:
SQL
application backend
external API
storage
CPU
locks
Data is better than guessing.
Another example: new server works by IP but not hostname
Bad test:
curl -k https://192.0.2.50
This may give misleading results.
Correct test:
curl \
--resolve portal.example.com:443:192.0.2.50 \
https://portal.example.com
Now you test:
correct hostname
correct SNI
correct TLS certificate
correct virtual host
correct application
before modifying DNS.
Another example: WireGuard tunnel
You expect all Internet traffic to leave through the VPN.
Before connecting:
curl https://api.ipify.org
Result:
80.1.2.3
After connecting:
curl https://api.ipify.org
Result:
91.1.2.3
If the address does not change, investigate:
AllowedIPs
routing
NAT
policy routing
default route
Simple.
Fast.
Unambiguous.
The commands every administrator should memorize
If you remember nothing else from this article, remember these.
Check website
curl https://example.com
Headers only
curl -I https://example.com
Verbose debugging
curl -v https://example.com
Follow redirects
curl -L https://example.com
Follow redirects and show headers
curl -IL https://example.com
Bypass DNS properly
curl \
--resolve example.com:443:192.0.2.10 \
https://example.com
Force IPv4
curl -4 https://example.com
Force IPv6
curl -6 https://example.com
API with bearer token
curl https://api.example.com \
-H "Authorization: Bearer $TOKEN"
Send JSON
curl https://api.example.com \
-H "Content-Type: application/json" \
-d '{"status":"test"}'
Test webhook
curl -X POST \
https://example.com/webhook \
-H "Content-Type: application/json" \
-d '{"test":true}'
Download file
curl -LO https://example.com/file.zip
Ignore response body and return HTTP status
curl -s \
-o /dev/null \
-w "%{http_code}\n" \
https://example.com
Measure response
curl -s \
-o /dev/null \
-w "DNS:%{time_namelookup} TCP:%{time_connect} TLS:%{time_appconnect} TTFB:%{time_starttransfer} TOTAL:%{time_total}\n" \
https://example.com
Public IP
curl https://api.ipify.org
Useful script mode
curl -fsS https://example.com/health
One more thing: do not immediately use -k
Sooner or later every administrator encounters:
SSL certificate problem
and someone says:
curl -k
Yes.
It will probably make the error disappear.
But that doesn't mean the problem disappeared.
It means you disabled the check that detected the problem.
Use -k to answer:
Is certificate validation the only thing preventing this connection?
Do not use it to answer:
How should we fix certificate validation?
Those are different questions.
Why cURL is so valuable
cURL is useful because it sits directly at the boundary between:
network
TLS
HTTP
API
application
That makes it an unusually good diagnostic tool.
A browser might tell you:
Something went wrong.
cURL can tell you:
DNS resolved to 192.0.2.20.
TCP connected in 21 ms.
TLS negotiated successfully.
Certificate validation succeeded.
Server returned HTTP 502.
Response came from nginx.
Total response time was 4.8 seconds.
That is actionable information.
The administrator's mindset
The most valuable part of cURL isn't memorizing 100 parameters.
It is understanding how to use it to isolate problems.
If something doesn't work:
Does DNS resolve?
↓
Can TCP connect?
↓
Does TLS work?
↓
Does HTTP work?
↓
Does authentication work?
↓
Does the API respond?
↓
Does the application behave correctly?
cURL lets you test almost every layer in that chain.
That is why it is useful on:
Linux servers
Windows servers
macOS
Docker hosts
Kubernetes environments
reverse proxies
firewalls
VPN gateways
cloud servers
CI/CD systems
monitoring servers
administrator laptops
Final thoughts
A good system administrator does not need a graphical application for every task.
Sometimes the fastest diagnostic tool is one command:
curl -v https://broken-thing.example.com
cURL is small.
It is fast.
It is scriptable.
It works almost everywhere.
It understands modern HTTPS.
It works with REST APIs.
It can test authentication.
It can simulate webhooks.
It can measure performance.
It can bypass DNS without destroying your hosts file.
It can help distinguish an application problem from a network problem in seconds.
And perhaps most importantly, it gives you evidence.
Not:
I think the server is slow.
But:
DNS: 11 ms
TCP: 24 ms
TLS: 81 ms
TTFB: 6.4 seconds
Not:
Maybe DNS is wrong.
But:
curl \
--resolve example.com:443:192.0.2.50 \
https://example.com
Not:
Maybe the VPN is working.
But:
curl https://api.ipify.org
before and after connecting.
That is the difference between guessing and troubleshooting.
And that is why cURL is a tool every administrator should know.