Networking Inspection and curl Fundamentals
Reading curl's output and exit codes to distinguish a network failure from an HTTP-level failure, and the core flags for making requests, following redirects, and inspecting responses from the command line.
What you'll learn
- Explain the difference between curl failing to connect at all and curl successfully receiving an HTTP error response
- Use curl's core flags to control method, headers, request body, and redirect following
- Explain why curl's own exit code alone is not sufficient to detect an HTTP-level failure like a 404 or 500
Prerequisites
Explanation
Every real command below runs only in your own terminal — this lesson's exercises model these decisions as data, never sending a real network request.
curl's own exit code tells you only whether curl itself succeeded at the networking mechanics — it resolved the hostname, connected, sent the request, and received some response. A non-zero curl exit code means something failed at that level: the hostname didn't resolve, the connection was refused or timed out, or (with certificate verification enabled) a TLS handshake failed. Critically, curl exiting 0 (success) does not mean the request "succeeded" in the sense a script usually cares about — a server responding with a 404 Not Found or a 500 Internal Server Error is still, from curl's networking-mechanics point of view, a fully successful exchange: curl connected, sent the request, and received a complete, valid HTTP response — it just happens to carry an error status.
This is why scripts that care about the actual HTTP status need to check it explicitly, not just rely on curl's exit code — either with curl's own --fail flag (which makes curl itself exit non-zero on an HTTP 4xx/5xx response, when you want that specific behavior) or by capturing the status code directly with -w "%{http_code}" and checking it in the script. Confusing these two failure levels — network-layer failure vs. HTTP-layer failure — is a genuinely common source of scripts that silently treat a real API error as a success, simply because curl itself didn't complain.
curl's most-used flags for everyday inspection: -s (silent, suppress the progress meter — useful in scripts), -i (include response headers in the output), -I (fetch only the headers, via a HEAD request), -L (follow redirects, which curl does not do by default), -X (set the HTTP method explicitly, like -X POST), -H (add a request header), and -d (send a request body, also implicitly setting the method to POST if none was specified).
Example
Modeling the distinction between curl's networking-level exit code and the HTTP-level status code it receives, as data.
function curlWouldSucceedAtNetworkingLevel(scenario) {
// Models curl's OWN exit code: 0 only if the networking mechanics themselves worked.
const networkFailures = ["dns-resolution-failed", "connection-refused", "tls-handshake-failed"];
return !networkFailures.includes(scenario);
}
console.log(curlWouldSucceedAtNetworkingLevel("http-404-response")); // true -- curl DID successfully receive a full response
console.log(curlWouldSucceedAtNetworkingLevel("connection-refused")); // false -- curl itself failed at the networking level
function isHttpLevelFailure(statusCode) {
return statusCode >= 400;
}
console.log(isHttpLevelFailure(404)); // true -- an HTTP-level failure, even though curl itself succeeded at connecting
console.log(isHttpLevelFailure(200)); // false -- a genuine, complete success at both levelsTry it yourself
Call isHttpLevelFailure with 500, and confirm a server error is correctly identified as an HTTP-level failure.
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Guided exercise
Guided exercise
This models choosing curl's core flags for a scenario only -- no real request is sent. Write chooseCurlFlags(needsRedirects, method, hasBody): start with ['-s'] (always silent); add '-L' if needsRedirects; add '-X' + method if method is not 'GET'; add '-d' if hasBody. Return the array in that exact order.
Checks: chooses the minimal flag set for a plain GET · adds -L when redirect-following is needed · adds -X and -d correctly for a non-GET request with a body
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Stuck? Get a hint.
Independent exercise
Independent exercise
This models distinguishing a network-level failure from an HTTP-level failure only -- no real request is sent. Write classifyOutcome(curlExitCode, httpStatus): if curlExitCode is not 0, return 'network-failure'. Otherwise, if httpStatus >= 400, return 'http-failure'. Otherwise, return 'success'.
Checks: correctly identifies a network-layer failure · correctly identifies an HTTP-layer failure despite curl itself succeeding · correctly identifies a genuine, complete success
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Stuck? Get a hint.
Common mistakes
- Assuming curl exiting 0 means the request 'succeeded' in every sense -- curl exits 0 as long as it successfully sent the request and received a complete response, even if that response is an HTTP 404 or 500.
- Forgetting -L when a URL might redirect -- curl does NOT follow redirects by default, so a script can silently receive an unexpected redirect response instead of the final target's actual content.
- Not checking the actual HTTP status code in a script that cares about it -- either via --fail (making curl itself exit non-zero on 4xx/5xx) or by capturing it explicitly with -w "%{http_code}", rather than assuming curl's own exit code covers this.
Knowledge check
Takeaway
curl's exit code reflects only the networking mechanics -- a complete, successfully received HTTP error response still counts as curl 'succeeding.' Use --fail or -w "%{http_code}" when a script needs to react to the actual HTTP status. Remember curl does not follow redirects unless -L is explicitly passed.
Summary
curl's own exit code tells you whether the networking mechanics worked (DNS, connection, TLS, receiving a complete response) -- not whether the HTTP status itself was a success. -L follows redirects (off by default). -X sets the method, -H adds headers, -d sends a body. --fail or -w "%{http_code}" are how a script actually checks the HTTP-level outcome.
References
Your notes
Notes save automatically.
Finished this lesson?
Mark it complete to track your progress and schedule a future review.
AI tutor
The optional AI tutor isn't enabled in this deployment. All lessons, exercises, quizzes, and search work fully without it.