Dev Learning Lab

The labs on this site need JavaScript to run. The same content is written out below.

Fundamentals › Networking

Cookies

What is a cookie, and who stores it and who sends it?

In HTTP, each request stands on its own, so the server cannot tell by itself whether a second request came from the same person as before. A cookie is a small value made to solve this. The code box shows the response text that the server sends back to the first request, and the Set-Cookie: visitor=alice line in it is the line that hands over a cookie. With this line, the server asks, "Keep this value, and show it to me when you come next time." It is the browser that stores the value and the browser that sends it back. The browser adds the stored value to the next request to the same server as a Cookie: visitor=alice header. The server in this lab is made to send back "Welcome back, value" when the value of visitor comes in the Cookie header of a request, and "Hello, new visitor" when it does not, and this server code is not shown on the screen. You remove the Set-Cookie line, delete the cookie before the second request, or send the requests with a program that does not store cookies, and see whether the server recognizes the second request when the same server is requested twice. The (empty line) in the code box is a way to show a line with no text at all, so that you can see it.

Checked against real execution · Ran 6 combinations with a net server on Node.js 24.18.0 and the cookie engine of curl 8.21.0, and checked against the results (not run in a browser)

Concepts in this lab

Cookie
A small piece of data that a server sends in a response. The browser stores it and automatically sends it back with every request to the same site. HTTP does not remember state between requests, so this data is used to keep information that must carry over, such as a login state. Because it is stored in the user's browser, you must use it on the assumption that the user can read or change its contents.
Set-Cookie header
Set-Cookie is a response header that a server adds to a response to send a cookie to the client (a user agent such as a browser) (RFC 6265 section 4.1). It starts with one "name=value", as in Set-Cookie: visitor=alice, and attributes such as expiry and path can be added after it. It means "Keep this value, and show it to me when you come next time." It is the receiving side that decides whether to store the value and return it on requests to the same server, so a program that does not store cookies does not use this line even when it receives it.
Cookie header
Cookie is a header that a client adds to a request when it returns a cookie it has stored to the server (RFC 6265 section 4.2). It writes only the stored "name=value", as in Cookie: visitor=alice, and does not carry attributes such as expiry or path (section 4.2.1). A browser adds this header to requests that meet the conditions for sending the cookie, so a developer does not write it in the code that sends requests. The server can read this header to tell which cookie the client of a request has, and it can also ignore the header (section 3).
HTTP as a stateless protocol
HTTP is a communication protocol in which a client sends a request and a server responds. Stateless means that the server does not remember the content of earlier requests, so each request must carry all the information needed to process it. Because the server keeps no state, any server can take a request, which makes it easy to add servers. Information that must carry over, such as a login state, is kept with cookies, sessions, or tokens.

Try these

Running with the default settings

  1. When you type localhost:8080 in the address bar of the browser, the browser sends a GET / request to the server. This request has no Cookie header.
  2. The server reads the request. There is no Cookie header, so it cannot tell who this is. In HTTP, each request stands on its own, so the server cannot tell by itself whether this request came from someone who came before. This server is made to send back "Welcome back, value" when a visitor value comes in the Cookie header, and "Hello, new visitor" when it does not. This server code is not shown on the screen.
  3. The server sends the response. The body is "Hello, new visitor", and the Set-Cookie: visitor=alice line from the code box is attached. This line means "Keep this value, and show it to me when you come next time."
  4. The browser receives the response and stores visitor=alice from the Set-Cookie line on its own side. The place where the value is stored is the browser, not the server. This server has no place to write down visitors.
  5. The browser sends a second request to the same server. A cookie that this server handed over is stored, so the browser adds the stored value to the request as a Cookie: visitor=alice header. We did not write the code that adds this header. The browser does it.
  6. The server reads the request. The Cookie header has visitor=alice, so it makes "Welcome back, alice" the body. The server did not remember this person. It only read the value that came with the request. A Cookie header has come, so this response gets no Set-Cookie line.
  7. The browser receives the second response. The body is "Welcome back, alice".

Result of this run

Code

HTTP/1.1 200 OK
Set-Cookie: visitor=alice
Content-Type: text/plain; charset=utf-8
(empty line)
Hello, new visitor

Assumptions of this model

The server is a single one started with the net module of Node.js 24.18.0 on a free port of 127.0.0.1. It reads the headers of a request up to the empty line, and sends back "Welcome back, value" if the Cookie header has a value for visitor, and "Hello, new visitor" if it does not. The Set-Cookie: visitor=alice line is attached only to the response to a request that has no Cookie header while the setting is on, and the connection is closed after sending. The first response the server sent is the same as the text in the code box, line by line (if it were made with the http module, headers such as Date would be added and the text would differ, so the text was sent exactly as it is with net, and Content-Length was not used, so the end of the response is shown by closing the connection). This server has no place to write down visitors, so when a new client without a cookie made a request after that, it did not recognize the earlier visitor. The client is curl 8.21.0 on the PC used to write this lab, which implements the cookie rules (RFC 6265). For the side that stores cookies, the same jar file was given to curl -b and -c (the cookie engine is turned on and cookies are saved to the file), and the stored cookie was obtained by reading the jar file after the first response. The user deleting the cookie was reproduced by giving a new empty jar file to the second request. The side that does not store cookies is curl without cookie options, and this curl did not add a Cookie header to the second request even though it received the Set-Cookie line of the first response. All 6 combinations were run, and the stored cookie, the Cookie header the server actually received in the second request, and the second response were checked against the model. The full headers of the two requests, the raw text of the two responses, and the arguments given to curl (there is no argument that writes a Cookie header by hand) were also checked. The check was made with the cookie engine of curl instead of a browser. Browsers also follow the same standard (RFC 6265), but the results of this lab were not run and checked in a real browser. What was checked against the documentation is RFC 6265 section 1 (the server sends a cookie with Set-Cookie, and the client decides whether to return it with Cookie in later requests), sections 3 and 3.1 (the example in which Cookie: SID=31d4d96e407aad42 is carried on the next request after receiving Set-Cookie: SID=31d4d96e407aad42), section 4.1 (Set-Cookie is the response header with which a server sends a cookie to a client), and section 4.2 (Cookie is the request header with which a client returns the cookies it has stored to the server), and that HTTP is a stateless protocol in which each request can be understood on its own follows section 3.3 of RFC 9110. The localhost:8080 on the screen is an example address, and the actual check was made on another port of the PC used to write this lab. Cookie attributes such as expiry, path, domain, Secure, HttpOnly, and SameSite were not covered, and the details are covered in the in-depth lab "Cookies". This server code is not shown on the screen.

Previous lab: HTTP responses · Next lab: JSON

Concepts in this lab

What this lab shows

Settings

Code


      
    

Diagram

Run comparison

Try these