Conceptly
← All Concepts
πŸͺ

HTTP Cookie

State ManagementSmall text fragments that maintain state between the browser and server

An HTTP Cookie is a small piece of text data that the server asks the browser to store. Whenever the browser sends a subsequent request to the same server, it automatically includes that cookie. Because the HTTP protocol itself is stateless and does not remember previous requests, without cookies the server has no way of knowing who sent each request. Cookies fill this gap, enabling state-based web experiences such as staying logged in, remembering shopping carts, and preserving user preferences. In addition to a name-value pair, a cookie carries an expiry time, the domain and path it applies to, and security attributes (HttpOnly, Secure, SameSite) that allow fine-grained control over when, where, and how it is transmitted.

β–ΆArchitecture Diagram

πŸ“Š Data Flow

Dashed line animations indicate the flow direction of data or requests

Why do you need it?

One of the most fundamental limitations of the web is that HTTP does not remember previous requests. When a user types a username and password into a login form and clicks submit, the server knows who they are at that moment. But as soon as the next page loads, the server treats the incoming request as a completely new and unfamiliar one. Add an item to a shopping cart and navigate to checkout, and the cart is empty. Turn on dark mode and refresh, and the bright screen comes back. Asking users to log in again on every request is not an option. If the server tried to remember all users' state on its own, it would have no thread to connect a request back to a specific user. HTTP's stateless design keeps the protocol simple, but it leaves an empty space when it comes to building continuous user experiences.

Why did this approach emerge?

In the early 1990s, the web was primarily a medium for retrieving and reading documents. A page would be requested, a response received, and that was the end of the interaction β€” there was no reason to remember what came before. But the arrival of e-commerce changed that. For a user to browse products, add them to a cart, and complete a purchase, something had to tie multiple requests together as belonging to the same person. The solution, proposed in 1994 by Netscape engineer Lou Montulli, was the cookie. The server would embed a small piece of text in its response, the browser would store it and attach it to every subsequent request. It was a practical workaround that layered state on top of HTTP without changing the protocol itself, and it was later standardized in RFC 2109 and RFC 6265, becoming a fundamental piece of web infrastructure.

How does it work inside?

The mechanics of a cookie form a cycle: the server plants it, and the browser returns it. When the server includes a Set-Cookie header in an HTTP response, the browser stores that name-value pair in the cookie store for that domain. From that point on, whenever the browser sends a request to the same domain, it automatically includes the stored cookie in a Cookie header. The developer does not need to modify any request code. Set-Cookie accepts several attributes beyond the name and value. Domain and Path define which requests the cookie should be attached to. Expires and Max-Age set the cookie's lifetime; without these attributes the cookie becomes a session cookie that disappears when the browser is closed. On the security side, the Secure attribute restricts the cookie to HTTPS connections, and HttpOnly prevents JavaScript from reading it, reducing the risk of cookie theft through XSS attacks. The SameSite attribute controls whether the cookie is sent with cross-site requests, providing a defense against CSRF attacks. Browsers impose limits on the number of cookies per domain and on total size, with a typical per-cookie maximum of around 4 KB. Because cookies are included automatically in every request, having many large cookies increases the network overhead of every request.

In Code

A server sets a cookie and the browser sends it back

export async function GET() {
  return new Response("ok", {
    headers: {
      "Set-Cookie": "sessionId=abc123; Path=/; HttpOnly; Secure; SameSite=Lax",
    },
  });
}

Read the attributes attached to `Set-Cookie`, then trace what the browser will automatically return on the next request.

Keep cookie values small because they ride along with every request

function getThemeCookie(cookieHeader: string | null) {
  return cookieHeader
    ?.split("; ")
    .find((part) => part.startsWith("theme="))
    ?.slice("theme=".length);
}

Focus less on parsing and more on the fact that a cookie is a small string that is sent with each request.

What is it often confused with?

Cookies and Web Storage (localStorage, sessionStorage) are similar in that both store data in the browser. The decisive difference is whether the data is sent to the server. Cookies are automatically included in every HTTP request to the matching domain. Web Storage lives entirely within the browser; to send that data to the server, the developer must explicitly extract it and attach it to a request. This difference determines their respective roles. Cookies are suited for authentication and session management, where the server needs to identify the user on every request. Web Storage is better for client-side UI state and temporary data that never needs to reach the server. Capacity is also very different -- cookies are limited to 4 KB while Web Storage offers 5 to 10 MB -- so stuffing large amounts of data into cookies inflates the size of every request unnecessarily. Cookies and JWT are also frequently compared. A cookie is a transport mechanism that carries data; JWT is a data format. In practice, storing a JWT inside a cookie is a common combination, as is putting a JWT in an Authorization header instead of a cookie. The question 'cookies vs JWT' conflates two things of different natures; a more accurate framing is 'server session + cookie vs JWT + cookie (or header)'.

When should you use it?

The cookie is the most fundamental link in web authentication. The pattern of issuing a session ID into a cookie after login and using it to identify the user on subsequent requests has long been the de facto standard. In server-rendered sites, where every page request itself requires authentication, the automatically transmitted cookie is essentially the only viable option. The most common judgment call in practice is setting security attributes correctly. Omitting HttpOnly means that if an XSS vulnerability exists, a script can read the session cookie directly. Setting SameSite to None exposes the site to CSRF. Sending a cookie over plain HTTP without Secure allows it to be intercepted in transit. Many security incidents originate from missing attribute settings, so the habit of reviewing attributes at the time a cookie is issued is important. Third-party cookies are increasingly constrained by strengthened privacy regulations and browser blocking policies. The use of cookies for tracking purposes is steadily declining, and a first-party-cookie-centered design is the direction going forward.

Maintaining login state -- carrying a session ID in a cookie to persist authenticationShopping cart -- keeping the list of items added by a non-logged-in userUser preferences -- remembering settings such as language and themeTracking and analytics -- storing identifiers to collect visit patterns