How HTTP Cookies Work

11 Aug 2019

An HTTP cookie is a tiny (4 KB) piece of data that a client (e.g. browser) stores locally.

Since HTTP is a stateless protocol, cookies act as a shared state that enable some truly great things (persistent login sessions), and some other not-so-great ones (ad-tracking).

Creating cookies

A cookie's life is conceived when a server responds to a request and instructs the client to set a cookie, using the aptly-named Set-Cookie HTTP header in the response.

HTTP/1.1 200 OK
Set-Cookie: user_id=123

A cookie can have several optional attributes too, which are separated by a semicolon (;), and appended to the end of the cookie value.

Set-Cookie: user_id=123; Expires=Wed, 11 Aug 2019 00:00:00 GMT; Secure; HttpOnly

This sets the expiry date of the cookie (Expiry), ensures it's only sent to the server via HTTPS (Secure), and doesn't expose it to the DOM APIs (HttpOnly).

Upon parsing the response header, the browser saves the cookie locally.

Setting multiple cookies

Cookies are standardised by the Internet Engineering Task Force (IETF) and explained in a RFC Document.

Initially, the behaviour of cookies was outlined in RFC 2109, which allowed multiple cookies to be "folded" into a single Set-Cookie header separated by a comma.

❌  The wrong way

Set-Cookie: user_id=123, app_theme=dark, likes_apples=true

As you can imagine, setting multiple cookies (along with their attributes) created long, unsightly header values. Probably realising this needed improvement, the IETF released RFC 6265 in 2011, which notably set a new rule:

Origin servers SHOULD NOT fold multiple Set-Cookie header fields into a single header field.

This was quickly adopted by all major browsers, and now allows for a much cleaner approach to creating multiple cookies.

✔️  The correct way

Set-Cookie: user_id=123
Set-Cookie: app_theme=dark
Set-Cookie: likes_apples=true

Returning cookies

The cookie's journey back to the server is through the Cookie header in the HTTP request.

GET /index.html HTTP/1.1
Cookie: user_id=123

In contrast to Set-Cookie, multiple cookies are folded into the same header value, and are a bit confusingly separated by a semicolon.

Cookie: user_id=123; app_theme=dark; likes_apples=true

You don't have to worry about setting cookie attributes in the request, because they are never returned back to the server. It's a one-way street for them, from server to client.


This was a brief overview of how HTTP cookies work, outlining some of the gotchas that I learnt the hard way while building a cookie middleware for a web server.

If you'd like to learn more about cookie attributes, or other areas not covered in this article, I recommend reading more at MDN.