Contents

10/07/2026

curl Exits 0 on a 404: Use --fail in Scripts

Short answer: curl's exit code says whether the transfer worked, not whether the server liked the request. A 404 or a 500 is still a completed transfer, so curl exits 0 and a script carries on. Add --fail (-f) and curl exits with code 22 on any HTTP status of 400 or higher. If you also want the error page text, use --fail-with-body.

What it looks like

We started a local web server with one page and asked curl for a page that does not exist (curl 8.19.0 on Windows):

curl -s -o /dev/null http://127.0.0.1:18771/nope.html
echo "exit $?"        # exit 0
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:18771/nope.html   # 404

The first command exits 0 even though the server answered 404. The second shows the status code was there all along: curl reports it only when you ask.

The fix

curl -sf -o /dev/null http://127.0.0.1:18771/nope.html
echo "exit $?"        # exit 22

With -f, the 404 gives exit code 22, and an existing page still exits 0, which we checked too. The curl manual describes --fail this way: "Fail with error code 22 and with no response body output at all for HTTP transfers returning HTTP response codes at 400 or greater" (curl manual, curl 8.23.0).

When you want the error text

--fail throws the error page away. The manual says --fail-with-body "allows curl to output and save that content but also to return error 22". We saw the same exit code 22 and the server's error page printed. Use it when a script should log why the server refused.

A caveat from the manual

The same manual says --fail "is not fail-safe and there are occasions where non-successful response codes slip through, especially when authentication is involved (response codes 401 and 407)". If a script depends on a particular status, ask for it with -w "%{http_code}" and compare it yourself.

What each form returns

  • curl URL (a 404)

    Exit 0. The status code is available with -w but does not change the exit code.

  • curl -f URL (a 404)

    Exit 22, with no body output.

  • curl --fail-with-body URL (a 404)

    Exit 22, with the server's error page printed.

  • curl URL (nothing listening)

    A non-zero exit. We saw 7 when connecting to a closed port.

In a script

if ! curl -sf -o page.html "$URL"; then
  echo "download failed" >&2
  exit 1
fi

This is the same family of trap as grep exiting zero when it finds the word FAILED and a gzip pipe that made a 20-byte backup: a command succeeds at its own job while your script needed something else. Test the failure path once, with a URL you know does not exist.

FAQ

Why does curl return 0 on a 404?

The transfer itself succeeded: the server answered. curl only treats an HTTP error status as a failure when you add --fail.

What does curl exit code 22 mean?

With --fail or --fail-with-body, it means the server returned an HTTP status of 400 or higher.

How do I get the status code from curl?

Use -w "%{http_code}" with -o to send the body elsewhere, and compare the value in your script.

Researched and drafted with AI, then reviewed and edited by the site's editors.

Filed under