The difference between HTTP status codes 401 and 403: Unauthorized and Forbidden

You are working with an API and after sending a request you receive one of these two HTTP response codes: 401 or 403. What do HTTP status codes 401 and 403 mean?

Official specification

If you search for the official specification, this is what you get:

401: Unauthorized

The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource. 

https://httpwg.org/specs/rfc7235.html#status.401

403: Forbidden

The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it. 

https://httpwg.org/specs/rfc7231.html#status.403

Hmmm…. 🤔 These two sound pretty similar to me. And to make things even more confusing, 403 “Forbidden” says that the server refuses to “authorize” the request but it’s code 401 that is called “Unauthorized”. 😵

Let’s simplify: airport analogy

You need a valid flight ticket to board a plane and the flight ticket has some information: your name and the gate number, for example, along with the destination, flight time, etc.

To simplify this analogy, the ticket has two parts: your identification (a username and a password to access the API) and your gate number (the resource you want to access).

If the ticket is incorrect or damaged, you cannot even go through the airport security: when they check your ticket, it will be refused. You are Forbidden to enter the boarding area of the airport.

Next, let’s say that your ticket is correct (so you made through security just fine!) and the gate number in your ticket says “Gate 24” but you walk to Gate 27. The attendant cannot authorize you to go through that gate because it’s not the right gate for your ticket.

In other words, an “incorrect ticket” is similar to messing up your credentials: wrong username and/or password and you receive back a 403 Forbidden. Using the correct credentials but trying to access a resource that is not allowed for those credentials returns you a 401 Unauthorized.

You can also think that 403 happens before 401, despite the natural number order: you will not receive a 401 until you resolve a 403.

A real example

The screenshot below shows that I try to login to my headspace account with a incorrect password (a “damaged” ticket in our analogy) and the response code in the network tab of the developer tools shows the 403.

screenshot of login page and developer tools network tab showing 403 status code
403 HTTP status code when trying to login with incorrect username or password

Important! Don’t believe everything you read!

One important thing to note here: the official specification is not enforced in any way and like many other things in software development, you might find out that the response codes are not consistent with the specification. If you are using a web framework, this will be configured out of the box and the return codes will work as specified but developers can override the base implementation and assign whichever code they want as responses.

Of course this is a bad idea because it will lead to confusion and it’s prone to error.

It takes just one Google search to prove to you that people mix these 2 status codes up all.the.time and there’s a chance that the API you are using got things backwards!

Here’s a horror story for you: I once worked with an API that only used GET methods (for modifying resources as well, instead of POST!!) and all response codes, for anything, were 200. 😱 So! Watch out!


If you found this helpful, please share this article!

HTTP 401 and 403 explained

The post The difference between HTTP status codes 401 and 403: Unauthorized and Forbidden was originally published at flaviabastos.ca