How to check HTTP status code

Print the code and nothing else: curl -s -o /dev/null -w '%{http_code}\n' https://api.example.com/orders. -o /dev/null throws the body away, -w writes the number. curl still exits 0 on a 404 or a 500, so add -f when a script has to treat those as failures.

Why check this

The status code is the first assertion in almost every API test, and the one most often asserted against the wrong thing. Run this check when a route changes, when a redirect is added, and whenever a pipeline step reports success on an API you know is broken. It catches the case where a deploy turns a 200 into a 302 to a login page and the test suite keeps passing because it only asserted that the call finished.

Prerequisites

Steps

  1. Step 1.

    Print the code for a working endpoint.

    curl -s -o /dev/null -w '%{http_code}\n' https://example.com/
    
    200
  2. Step 2.

    Print the code for an endpoint that fails.

    curl -s -o /dev/null -w '%{http_code}\n' https://httpbin.org/status/500
    
    500
  3. Step 3.

    Read the code of a route that redirects, without following it.

    curl -s -o /dev/null -w '%{http_code}\n' 'https://httpbin.org/redirect-to?url=https%3A%2F%2Fexample.com%2F&status_code=302'
    
    302
  4. Step 4.

    Follow the redirect and see which code -w reports then.

    curl -sL -o /dev/null -w 'final=%{http_code} redirects=%{num_redirects} url=%{url_effective}\n' 'https://httpbin.org/redirect-to?url=https%3A%2F%2Fexample.com%2F&status_code=302'
    
    final=200 redirects=1 url=https://example.com/

    With -L the reported code belongs to the last hop. %{num_redirects} is the only sign that the first hop was not a 200.

  5. Step 5.

    Read the exit code curl returns on a 404.

    curl -s -o /dev/null https://httpbin.org/status/404; echo "exit=$?"
    
    exit=0

    The request completed, so curl calls it a success. A shell script that tests $? here reports the API healthy.

  6. Step 6.

    Add -f and read the exit code again.

    curl -sf -o /dev/null https://httpbin.org/status/404; echo "exit=$?"
    
    exit=22

How to read the result

| What you see | What it means | What to do | | --- | --- | --- | | 2xx | The server handled the request | Assert the exact number. 200 and 201 are different contracts and clients read them differently. | | 3xx | The resource moved or the client is being sent elsewhere | Follow it once with -L and compare %{url_effective} against the URL you asked for. | | 401 or 403 | The credential is missing or the credential is not allowed | 401 means authenticate, 403 means the identity is known and refused. Fix the one the API actually returned. | | 404 on a route that exists | Wrong path, wrong base URL, or a router that hides unauthorised routes | Compare against the same call with a valid token before filing a bug. | | 5xx | The server broke while handling a valid request | This is always a defect on the server side, including 502 and 504 from a proxy. | | 000 | No HTTP response arrived at all | DNS, TLS or connection failure. Read curl's exit code instead of the status. |

Common mistakes

Sign: The pipeline step is green and the API returns 500.Cause: curl exits 0 whenever it received a complete response, whatever the status. Step 5 shows exit=0 on a 404. Only -f turns an HTTP error into exit code 22, and only for codes at 400 and above.
Sign: The status check says 200 and the client still gets logged out.Cause: With -L, %{http_code} reports the final hop. A 302 to a login page followed by a 200 on that page reads as 200. Print %{num_redirects} beside it, or drop -L when you are asserting the code of one route.
Sign: With -f the code is right but the error message is gone.Cause: -f discards the response body on an HTTP error, which is where APIs put the machine readable reason. Use --fail-with-body on curl 7.76 or later to keep the exit code and the JSON error together.

What to check next

FAQ

Is there an HTTP status code checker that needs no install?

Any browser DevTools Network tab shows the code per request, and the curl one liner above needs nothing beyond curl. Avoid pasting an internal staging URL into a third party status checker, because the request then comes from that vendor's network and not from yours.

How do I check the status code in the browser?

Open DevTools, Network tab, reload, then read the Status column. Click the request and open the Headers panel for the full status line. Chrome greys out requests served from cache, which report 200 without touching the server.

Why does curl print 000?

No HTTP response was received, so there is no code to print. The cause is in curl's own exit code, which is 6 for a name that does not resolve and 28 for a timeout.

Can I get the code for every hop of a redirect chain?

Not from -w, which writes once per transfer and reports the last hop. Print the status lines instead: curl -sIL URL | grep -i '^HTTP/' returned HTTP/2 302 then HTTP/2 200 for the redirect in step 4.

Verified

Verified by Maks Vernycurl 8.21.0

Each output block is what the command above it printed on that date, on the host named in the step. Figures read from a live site move between runs. Compare the shape of the answer rather than the digits, and see the methodology for how a page is re-verified.

basic3 minpublished updated Maks Verny