Understanding browser cookies 🍪
Tags: javascript, webdev, beginners
Published: 2021-04-26 01:26:22

---
title: Understanding browser cookies 🍪
published: true
date: 2021-04-05 12:31:04 UTC
tags: javascript, webdev, beginners
canonical_url: https://chenhuijing.com/blog/understanding-browser-cookies/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3gg2wb0xrzahncvh3u3.jpg
---

Even though I’ve been doing web things for a while now, I confess I had never dealt with browser cookies other than clicking those cookie notifications on every other website you visit these days.

I mean, I knew that it was a form of storage on the browser, but I’d always used `localStorage` for that. Recently I was working on something that used browser cookies and I figured it was a good time to figure them out.

## Why cookie and not some other tasty snack?

I love the name cookie, but I can’t help but wonder if there was a reason for it. Turns out I’m not the only person who had that question. And the inventor of browser cookies, [Lou Montulli](http://montulli.blogspot.com/2013/05/the-reasoning-behind-web-cookies.html) explained that he had heard the term ‘magic cookie‘ from an operating systems course in college that had a similar meaning to the way his proposed solution for a session identifier worked.

The original problem he was trying to solve was the implementation of an online shopping cart, which eventually led to the [original specification](https://curl.se/rfc/cookie_spec.html) for persistent client state, and has since evolved into the current [RFC 6265](https://tools.ietf.org/html/rfc6265). The first cookies were used to verify repeat visitors to the Netscape website.

## So how does this non-edible cookie work?

A cookie is a small plain text file stored in the browser. There isn’t anything executable in there. It simply contains a small amount of data. Every browser stores them in a slightly different location (e.g. [Where cookies are located in Windows 10, for all web browsers](https://www.digitalcitizen.life/cookies-location-windows-10/)).

The data in the cookie is sent over by the server, stored on the user’s browsers, then used in subsequent requests as an identifier of sorts. Cookies are mainly used to remember state (if you are logged in, shopping cart items, user preferences etc.) as well as tracking.

Cookies are created when the server sends over one or more `Set-Cookie` headers with its response, something along these lines:

```
Set-Cookie: NAME=VALUE
```

It could be any name-value pair, but each cookie can contain only 1 name-value pair. If you need more than 1 cookie, then multiple `Set-Cookie` headers are needed. An example of a server sending over cookie headers to the browser looks something like this:

```
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: viola=red_panda
Set-Cookie: mathia=polar_bear
```

As a frontend developer, I must admit I don’t debug server-sent headers very often so this is not something I see on a regular basis. Once the cookie is set, all subsequent requests to the server from the browser will also have the cookies in its request header.

```
GET /demos/cookie/ HTTP/2
Host: huijing.github.io
Cookie: viola=red_panda; mathia=polar_bear
```

Even though cookies are usually created on the server, you can also create them on the client-side with Javascript, using `document.cookie`. Browser cookies also have a number of attributes in addition to the name-value pair mentioned earlier.

## Cookie attributes

The cookie name can be any US-ASCII characters except control characters, spaces, tabs or separator characters. The cookie value can be optionally wrapped in double quotes and be any US-ASCII characters except control characters, double quotes, commas, semicolons, backslash and whitespace.

Adding special prefixes to the cookie name also forces certain requirements. If your cookie name starts with ` __Secure-`, it must be set with the `secure` flag from a page served with `HTTPS`. If your cookie name starts with `__ Host-`, it must be set with the `secure` flag from a page served with `HTTPS`, it must not have a domain specified and its path must be `/`.

The rest of the attributes are optional but can impact cookie behaviour significantly depending on what values are set.

### `Expires=<date>`

When a cookie passes its expiry date, it will no longer be sent with browser requests, and instead will be deleted. The date value is a HTTP timestamp.

### `Max-Age=<number>`

Also related to a cookie’s expiry, but in seconds. After the specified amount of time, the cookie will expire, so setting it to 0 or a negative number means instant expiry. `Max-Age` takes precedence over `Expires` if both are set.

### `Domain=<domain-value>`

Specifies the host where the browser cookie gets sent to. Only a single domain is allowed. If not present, this defaults to the current document URL’s host. When specified, all sub-domains are included as well.

### `Path=<path-value>`

Cookie will only be sent if the path exists in the current URL

### `Secure`

Cookie will only be sent when the request is made with HTTPS

### `HttpOnly`

Javascript cannot access the cookie through `document.cookie` (to mitigate XSS attacks)

### `SameSite=<samesite-value>`

Specifies if a cookie is sent with cross-origin requests.
- `Strict` means the cookie is only sent for requests originating from the same URL as the current one.
- `Lax` means the cookie is not sent on cross-site requests, but will be sent if the user navigates to the origin site from an external site.
- `None` means the cookie will be sent on both same-site and cross-site requests, but can only be used if the `Secure` attribute is also set.

If you use Firefox, you may notice a console log message like this on some websites.

![Console message in Firefox stating Some cookies are misusing the SameSite attribute, so it won't work as expected](https://chenhuijing.com/assets/images/posts/cookie/samesite-1280.png)

Back in August 2020, Mozilla [made the decision](https://hacks.mozilla.org/2020/08/changes-to-samesite-cookie-behavior/) to treat cookies as `SameSite=Lax` by default, and require cookies with `SameSite=None` to also set the `Secure` attribute. The original behaviour for cookies was `SameSite=None` but this leaves users susceptible to [Cross-Site Request Forgery](https://developer.mozilla.org/en-US/docs/Glossary/CSRF) attacks.

Both Chrome and Firefox has rolled this out, but it seems like only Firefox displays the console log warning? If you can verify the console logging situation, please let me know.

## Using cookies to do stuff

Cookies without an `Expires` or `Max-Age` attribute are treated as session cookies, which means they are removed once the browser is closed. Setting a value on either `Expires` or `Max-Age` makes them permanent cookies, since they will exist until they hit their expiry date.

Again, I usually don’t do server-side stuff so I’ll only talk about messing around with cookies on the client-side. The `Document` has a `cookie` property that lets us read and write browser cookies via Javascript.

To see all cookies associated with the document, use `document.cookie`. You can type this in the browser’s console and see something like this:

![Running document.cookie in the browser console](https://chenhuijing.com/assets/images/posts/cookie/allcookies@2x.png)

To create a new cookie, you can do something like this:

```javascript
document.cookie = "xiaohua=tortoise"
```

If you need more than one cookie, you’ll have to do this for every cookie you want to create.

![Create a new cookie in the browser console](https://chenhuijing.com/assets/images/posts/cookie/create@2x.png)

Even if you refresh the page, the cookie should still be there. To get rid of the cookie, or reset it, you can set the `Expires` value to the beginning of time itself, `Thu, 01 Jan 1970 00:00:00 GMT`. I’m semi-kidding. Just in case you never heard of this interesting (and fairly important) piece of trivia, I shall quote MDN:

> A JavaScript date is fundamentally specified as the number of milliseconds that have elapsed since midnight on January 1, 1970, UTC. This date and time are not the same as the UNIX epoch (the number of seconds that have elapsed since midnight on January 1, 1970, UTC), which is the predominant base value for computer-recorded date and time values.

For example, if I wanted to get rid of the `taria` cookie, I would do this:

```javascript
document.cookie = "taria= ;expires=Thu, 01 Jan 1970 00:00:00 GMT"
```

![Reset a cookie in the browser console](https://chenhuijing.com/assets/images/posts/cookie/reset@2x.png)

Because cookies are strings, doing things based on cookie data involves mostly string manipulation. So I won’t go into that in detail, but here’s [a ridiculous demo](https://huijing.github.io/demos/cookie/) you can play around with, ideally with DevTools open. It just randomly assigns a group cookie, then shows you something different based on that.

[![Screenshot of cookie demo site](https://chenhuijing.com/assets/images/posts/cookie/demo-1280.png)](https://huijing.github.io/demos/cookie/)

## Wrapping up

It’s been a while since I last published anything. I suppose this is the longest hiatus I’ve had since I started this blog, but somehow being stuck in the same place doesn’t seem to motivate me to write words. But we’ll see.

Meanwhile, go eat some of your favourite cookies.

## Resource links

- [Cookies, Chaos and the Browser: Meet Lou Montulli](https://blogs.gartner.com/martin-kihn/cookies-chaos-and-the-browser-meet-lou-montulli/)
- [Using HTTP cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)
- [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) on MDN
- [Document.cookie](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie) on MDN

_<small>Credits: OG:image from <a href="https://youtu.be/9pfL8-MP39Y"> Red Panda Loves Cookies</a> video on Oregon Zoo Youtube channel</small>_