The difference between 403 and 401, and when a 404 is the safer reply
Runs in your browser. Nothing you type is sent anywhere. Updated on 25 Oct 2026.A 403 means the server knows exactly who you are and is still refusing. Better credentials will not change the answer, which is what separates it from a 401. Send it for a missing role or scope, a read-only key used to write, a blocked address, or one account reaching another account's data.
Open the page with 403 Forbidden already selected.
Read "When to use it" for the usual causes: a missing role or scope, a blocked IP address or a read-only key used to write.
Select 401 in the Codes list to compare: a 401 can be fixed with better credentials, a 403 cannot.
Read the note on answering 404 instead when a private resource should not be seen to exist.
Some APIs deliberately answer 404 instead, so an attacker cannot learn which private records exist.
This HTTP status codes reference lists every registered code from 100 to 511, plus the unregistered ones that nginx, Apache, Laravel and Cloudflare return. Each entry says what the code actually means, when to send it, whether a cache may store the response without cache headers, whether a redirect changes the request method, and which RFC defines it.
Search works three ways. Type a number such as 404, or a class such as 4xx, to jump straight to it. Type a name such as "not found". Or describe what you want to express, and the intent search finds the code: "login failed" gives 401, "rate limit" gives 429, "file too large" gives 413, "validation failed" gives 422.
Every common code comes with a copyable snippet for raw HTTP, Express, Fastify, FastAPI, Go and PHP, including the header that code requires, such as WWW-Authenticate on a 401 or Allow on a 405. Nothing is sent anywhere; the whole table is in the page.
The rest of the article, and all 6 questions about HTTP Status Codes, are on the HTTP Status Codes page.
Use 401 Unauthorized. It means the server does not know who you are, so a missing, expired or wrong credential belongs there. Use 403 Forbidden only when you know who the caller is and are still refusing. The specification wants a WWW-Authenticate header on every 401.
401 means unauthenticated: send credentials and try again. 403 means authenticated but not allowed: better credentials will not help. If revealing that a record exists is itself a leak, some APIs answer 404 instead of 403 so an attacker learns nothing.
RFC 9110 section 15.1 lists 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414 and 501 as heuristically cacheable, and RFC 7725 adds 451. A cache may store those with no Cache-Control or Expires header, which is why a temporary 404 can persist. Every other code needs explicit cache headers.
No. 499 is an nginx log-only code for a client that hung up, and 520 to 527 are Cloudflare codes for problems between the edge and your origin. None are registered with IANA. They are listed here because you will meet them in logs, each marked with the product that invented it.
Still stuck? Ask about HTTP Status Codes and anybody who knows can answer. No account needed.
Same job, other tools: Luhn Algorithm Checker – Run the Luhn mod 10 check on any number and see every doubled digit and the total.
On the related tools: Hadolint Online – Run hadolint rules on a Dockerfile in your browser, with no install and no Docker · Readability Checker – Flesch reading ease and grade level, with what to change.
In the collection Debug and Inspect.