——
GuideTOOLS

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.

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.

curlsysadminLinuxWindowsmacOSnetworkingHTTPHTTPSREST APItroubleshootingDevOpscybersecurity

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.