An HTTP cookie is a tiny (4 KB) piece of data that a client (e.g. your browser) stores locally.
Since HTTP is a stateless protocol, cookies act as a shared, persistent state between the client and sever, enabling you to build complex applications. For example, cookies allow you to preserve login sessions when closing a browser tab.
While cookies can also be created by the client, server-originating cookies are the most common, so this article will focus on that.
The client stores a cookie when the server instructs it to do so. This instruction comes by the way of a specific header in the response to the client's HTTP request:
HTTP/1.1 200 OK Set-Cookie: user_id=123
This creates a cookie with name of
user_id and value of
A cookie may have several attributes too, which are separated by a
;), and appended to the end of the header value.
Set-Cookie: user_id=123; Domain=example.com; HttpOnly
This creates a new cookie with the following attributes:
Expiry- Date at which the cookie expires
MaxAge- Number of seconds until the cookie expires
Domain- Host to where the cookie is sent
Path- Path that must exists in the URL for the client to return the cookie
HttpOnly- Client can only send the cookie back to the server over HTTPS
Creating multiple cookies
A little bit of history; there is an old, deprecated way and a new standard. Cookies are standardised by the Internet Engineering Task Force (IETF) and explained in a Request For Comments (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.
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, in 2011 the IETF released RFC 6265, 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
Once a cookie is created, the client sends the cookie back to the server on
every request. The cookie's journey back to the server is through the
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
Cookie attributes are never returned to the server. They are instructions meant for the client from the server.
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.