07/10/2026 17:10pm

Cookie vs Session: How Websites Remember You Are Logged In
#cookie vs session
#what is a session
#session cookie
#httponly cookie
#localstorage vs cookie
#set-cookie header
#samesite cookie
Picture this: you logged in to a website yesterday, closed the tab, and came back today. The site still greets you by name, and you never typed your password again. People who are just starting web development ask our team some version of "how does the site remember me?" all the time, and the answer always lands on two words that get said together: Cookie and Session.
The trouble is that the two words get used so loosely that many beginners assume they are the same thing. Today Superdev Academy walks through what each one actually is, how they work together, and what the real headers passing between the browser and the server look like, so you can see for yourself that there is nothing mysterious going on.
Why does a website need help remembering you when HTTP remembers nothing?
Every time the browser asks for a page, it sends a Request to the server and the server sends back a Response. That is the whole exchange. HTTP is designed to be Stateless: the server does not remember who sent the previous Request. The cookie standard itself, RFC 6265, says so in its abstract: cookies let servers maintain a stateful session over the mostly stateless HTTP protocol.
Without some help, you would have to log in again every time you clicked to a new page, because to the server every Request comes from a stranger. Cookies and Sessions together solve that problem, but they do different jobs.
What is the difference between a cookie and a session? A coat check and a claim ticket
Think of the coat check at a theatre. You hand your coat to the attendant, who hangs it on a rail behind the counter and gives you a small ticket. On your way out you hand the ticket back, and the attendant finds the right coat.
The Session is the rail behind the counter. Your actual data, such as who you are, whether you are logged in and what is in your cart, is kept on the server side.
The Cookie is the ticket in your hand. It does not contain the coat. It only carries a reference that points to the coat, which on the web is called a Session ID.
Two lines worth remembering:
Cookie: stored in the browser
Session: stored on the server
If the ticket is lost or stolen, whoever holds it can collect your coat. That is why cookie security matters so much, and we will come back to it in the attributes section below.
Cookies and Sessions are not rivals. Most of the time they work as a pair: the Cookie holds the ticket, the Session holds the coat.
Real headers: Set-Cookie and Cookie
The whole mechanism lives in just two headers. When the server wants the browser to hold a ticket, it sends a Set-Cookie header with the Response. From then on, every Request the browser makes to the same site automatically carries a Cookie header back.
Our team ran curl against GitHub's login page on 29 September 2026 and got these headers back (the very long value is shortened):
set-cookie: _gh_sess=CV5197blwy...; path=/; HttpOnly; secure; SameSite=Lax
set-cookie: logged_in=no; expires=Wed, 29 Sep 2027 04:40:57 GMT; domain=.github.com; path=/; HttpOnly; secure; SameSite=LaxNotice that we had not logged in at all, yet GitHub had already issued a ticket, and logged_in=no says plainly that we are still a stranger. The first cookie, _gh_sess, has no expires. That detail matters, and we will explain why in the next section.
To see both sides, our team wrote a tiny Node.js server, under 20 lines, that creates a Session on login, then hit it with curl. This is the actual output:
$ curl -i localhost:3456/login
Set-Cookie: sid=fdcada48136db79c388c5993fefcdc22; Path=/; HttpOnly; Secure; SameSite=Lax
logged in
$ curl localhost:3456/me
who are you?
$ curl -H "Cookie: sid=fdcada48136db79c388c5993fefcdc22" localhost:3456/me
hello somchaiThe last line is the heart of it. The sid value is just random characters; the name somchai is nowhere inside it. The name lives in the server's memory. When we send the same ticket back in the Cookie header, the server looks it up on its own rail and knows who we are straight away. A Request with no ticket gets told the server does not know us.
The rules printed on the ticket: HttpOnly, Secure, SameSite, Expires
Everything after a ; in Set-Cookie is an attribute: an instruction from the server telling the browser how to handle this ticket. Four are worth knowing from day one (descriptions follow the MDN Set-Cookie reference):
Expires / Max-Age: how long the ticket lives.
Expirestakes a date,Max-Agetakes a number of seconds, and if both are set,Max-Agewins. If neither is set, the cookie becomes a session cookie that is removed when the browser shuts down. That is why GitHub's_gh_sesscarries no expiry.HttpOnly: JavaScript cannot read the cookie through
document.cookie. This limits the damage from XSS (injected malicious scripts), because even if a hostile script runs, it cannot grab the ticket. The cookie is still sent withfetch()requests as usual.Secure: the cookie is only sent over
https:(localhost excepted), so the ticket cannot leak on an unencrypted network.SameSite: controls whether the cookie is sent with requests that come from another site.
Strictsends it only for same-site requests,Laxalso sends it when the user follows a link in from another site, andNonesends it everywhere but must be paired withSecure. It helps protect against CSRF, where another site tricks your browser into sending a request on your behalf.
The SameSite default deserves care. The Chromium team announced that from Chrome 80 onwards, cookies without a SameSite attribute are treated as SameSite=Lax. MDN, however, says only "some browsers" do this, not all of them. The safe conclusion is to always set SameSite explicitly rather than relying on any one browser's default.
What about localStorage? Can it replace cookies?
Yes, and in many cases it is the better tool. MDN itself recommends the Web Storage API, localStorage and sessionStorage, over cookies for client-side data such as a user's chosen theme. Cookies are sent with every Request, so lots of them can slow a site down, especially on mobile data. localStorage never goes to the server, and its data has no expiration time until something deletes it. Despite the name, sessionStorage has nothing to do with the server-side Session in this article: it is browser Web Storage kept per tab, and closing the tab or window clears it.
Things change when the data is a proof of identity. localStorage has no equivalent of HttpOnly: any script running on the page can read all of it. If the page ever suffers an XSS attack, the ticket leaks immediately, whereas a Session ID in an HttpOnly cookie is better protected in the same situation.
Put simply: data that is not secret and that the server does not need can live in localStorage. For the ticket that says who you are, a cookie with the right attributes is still the standard choice.
JWT: the option without a coat rail
Some systems do not want the server to remember every Session. Instead, they write the user's details into the ticket itself and sign it so it cannot be forged. That kind of ticket is a JWT (JSON Web Token): the server only checks the signature instead of looking anything up. The trade-offs take some explaining, so we cover them separately in What is a JWT token. And if you want to see how a server responds when the ticket is missing or invalid, read about 401 in HTTP status codes explained.
Is the "accept cookies" banner the same thing?
Technically it is the same kind of cookie, but it is a different question. The cookie that remembers your login Session is something the site needs in order to work. The consent banners that pop up are mostly about analytics or advertising cookies, which MDN lists under Tracking, separate from Session Management. We have already written about consent in What is accepting cookies and why should you accept them, so this article sticks to the mechanism.
If you want the bigger picture of where a Session sits in a web system, Exploring the World of Web Development: Front End, Back End, and Full Stack shows that the coat rail belongs on the Back End. And when you are ready to try it in Go, Go and WebSocket Security has an example of using Sessions for authentication.
Summary: what is the difference between a Cookie and a Session?
A Cookie is the ticket the browser holds and sends back with every Request. A Session is the real data the server keeps and looks up with that ticket. The two work together to solve one problem: HTTP remembers no one. If you keep just one sentence, keep this one: the data lives on the server, the browser only holds the ticket, and a good ticket always carries HttpOnly, Secure and SameSite.
The fastest way to really understand this is to open your browser's DevTools, go to the Network tab, and log in to a site you use every day. Look for the Response that carries Set-Cookie, then check which Cookie the next Request sends back. Five minutes with the real thing teaches more than reading a definition ten times.
Follow more articles and tips for people starting out as programmers on our channels.
Facebook: Superdev School (Superdev) — https://www.facebook.com/superdev.school.th
Instagram: superdevschool — https://www.instagram.com/superdevschool/
TikTok: superdevschool — https://www.tiktok.com/@superdevschool
Website: www.superdevacademy.com — https://www.superdevacademy.com/
FAQ: Frequently Asked Questions about This Article
A collection of questions and answers to help you better understand the content of this article.