httpcode

View script Copied!

Quick reference for HTTP status codes. Look up what any status code means without leaving the terminal.

This is a lookup tool that prints descriptions of HTTP status codes from embedded MDN reference data. Think of it as a cheat sheet: you see 418 in a log, run httpcode 418, and get the name and description instantly. For timing HTTP requests (phase breakdown, summary statistics, outlier detection), see curl-timing.

Quick start

$ httpcode 404
404 Not Found

The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404

Common examples

Check what the teapot code means:

$ httpcode 418
418 I'm a teapot

The server refuses the attempt to brew coffee with a teapot.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/418

Understand rate limiting:

$ httpcode 429
429 Too Many Requests

The user has sent too many requests in a given amount of time (rate limiting).

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429

Look up a Cloudflare-specific code:

$ httpcode 522
522 Connection Timed Out (Cloudflare)

Non-standard Cloudflare code. Cloudflare could not negotiate a TCP handshake with the origin server.

https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/

Coverage

All standard HTTP status codes from MDN are included:

Plus common non-standard vendor codes:

The data is embedded in the script, so no network access is required. The current snapshot date is stored in the _snapshot field of the embedded JSON.

Updating the data

The embedded data rarely changes — MDN occasionally tweaks descriptions, vendors occasionally add a new non-standard code. Aim to refresh once a year or after noticing stale wording.

Step 1: Scrape MDN

Open https://developer.mozilla.org/en-US/docs/Web/HTTP/Status in a browser. Paste this into the DevTools console:

copy(JSON.stringify(Object.fromEntries(
    [...document.querySelectorAll('article > section dt:not(.bc-legend-item-dt)')].map(dt => [
        dt.id.substring(0, 3),
        {
            name: dt.querySelector('code').innerText.substring(4),
            message: dt.nextElementSibling.innerText
        }
    ])
)));

This copies a JSON object keyed by status code to the clipboard. Paste it into a file:

pbpaste > /tmp/statuses-mdn.json

If the scrape breaks (MDN changed their HTML structure), the selectors to update are at the top of the snippet. The page layout is: each code is a <dt> with id="NNN_name", containing a <code> with the text NNN Name, followed by a <dd> with the description. Inspect one <dt> in DevTools to re-derive the selectors.

Step 2: Maintain the vendor codes by hand

Keep this JSON here in the doc — if a vendor adds or renames a code, edit it in place. Save as /tmp/statuses-vendor.json:

Each vendor entry includes a source field pointing at the authoritative docs for that code. The script prefers this per-entry URL over the default MDN base, which means lookups for vendor codes land on the vendor's own docs instead of a 404 on MDN.

{
    "440": {"name": "Login Time-out (IIS)", "message": "Non-standard IIS code. The client's session has expired and must log in again.", "source": "https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#Internet_Information_Services"},
    "444": {"name": "No Response (nginx)", "message": "Non-standard nginx code. The server returns no information and closes the connection. Used to deter malicious clients.", "source": "https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return"},
    "449": {"name": "Retry With (IIS)", "message": "Non-standard IIS code. The server cannot honor the request because the user has not provided the required information.", "source": "https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#Internet_Information_Services"},
    "494": {"name": "Request Header Too Large (nginx)", "message": "Non-standard nginx code. The client sent too large a request or too long a header line.", "source": "https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#nginx"},
    "499": {"name": "Client Closed Request (nginx)", "message": "Non-standard nginx code. The client closed the connection while the server was still processing the request.", "source": "https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#nginx"},
    "520": {"name": "Web Server Returned an Unknown Error (Cloudflare)", "message": "Non-standard Cloudflare code. Cloudflare encountered an empty, unknown, or unexpected response from the origin server.", "source": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/"},
    "521": {"name": "Web Server Is Down (Cloudflare)", "message": "Non-standard Cloudflare code. The origin server refused connections from Cloudflare.", "source": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/"},
    "522": {"name": "Connection Timed Out (Cloudflare)", "message": "Non-standard Cloudflare code. Cloudflare could not negotiate a TCP handshake with the origin server.", "source": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/"},
    "523": {"name": "Origin Is Unreachable (Cloudflare)", "message": "Non-standard Cloudflare code. Cloudflare could not reach the origin server (DNS resolution failure or no route to host).", "source": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/"},
    "524": {"name": "A Timeout Occurred (Cloudflare)", "message": "Non-standard Cloudflare code. Cloudflare was able to complete a TCP connection but timed out waiting for an HTTP response.", "source": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/"},
    "525": {"name": "SSL Handshake Failed (Cloudflare)", "message": "Non-standard Cloudflare code. Cloudflare could not negotiate a SSL/TLS handshake with the origin server.", "source": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/"},
    "526": {"name": "Invalid SSL Certificate (Cloudflare)", "message": "Non-standard Cloudflare code. Cloudflare could not validate the SSL certificate on the origin server.", "source": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/"},
    "527": {"name": "Railgun Error (Cloudflare)", "message": "Non-standard Cloudflare code. The request timed out or failed after the WAN connection was established.", "source": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/"},
    "530": {"name": "Origin DNS Error (Cloudflare)", "message": "Non-standard Cloudflare code. 1XXX error from Cloudflare (see the 1XXX code in the response body).", "source": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/"}
}

Authoritative sources to spot-check:

Step 3: Merge and produce the final JSON

With statuses-mdn.json (from Step 1) and statuses-vendor.json (from Step 2):

jq -s --arg snapshot "$(date +%Y-%m-%d)" '
    .[0] * .[1] + {
        _source: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status",
        _snapshot: $snapshot,
        _sources: {
            mdn:        "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status",
            cloudflare: "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/",
            nginx:      "https://nginx.org/en/docs/http/ngx_http_core_module.html",
            iis:        "https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#Internet_Information_Services"
        }
    }
' -c /tmp/statuses-mdn.json /tmp/statuses-vendor.json > /tmp/statuses-merged.json

The -s slurps both files into one array; .[0] * .[1] deep-merges them (vendor entries win on conflict, so you can override MDN wording for a given code by adding an entry to the vendor JSON); the trailing object stamps the metadata; -c produces a single compact line, which is what the script expects.

Step 4: Paste into httpcode

Copy /tmp/statuses-merged.json to your clipboard:

pbcopy < /tmp/statuses-merged.json

Open /repo/sh/httpcode and replace the single JSON line inside the heredoc (the line between <<'EOF' and EOF) with the new content. Keep the surrounding bash unchanged.

Then run the tests to confirm the script still parses everything correctly:

/bin/bash /repo/sh/test-runner.sh httpcode

Reference

All options

Flag Description
-h, --help Show help message

Exit codes

Code Meaning
0 Success (code found and displayed)
2 Usage error (missing or unknown status code)
3 Dependency error (jq not installed)

Dependencies