[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"academy-blogs-en-1-1-all-cookie-vs-session-explained-all--*":3,"academy-blog-translations-rnj71f99yfx3r2p":92,"academy-blog-faqs-rnj71f99yfx3r2p-en":93},{"data":4,"page":91,"perPage":91,"totalItems":91,"totalPages":91},[5],{"alt":6,"collectionId":7,"collectionName":8,"content":9,"cover_image":10,"cover_image_l_url":11,"cover_image_m_url":12,"cover_image_path":13,"cover_image_s_url":14,"created":15,"created_by":16,"expand":17,"id":84,"keywords":85,"locale":54,"published_at":86,"scheduled_at":71,"school_blog":80,"short_description":87,"status":78,"title":88,"updated":89,"updated_by":90,"slug":81,"views":83},"A coat-check counter where a hand receives a blank claim ticket while coats hang on a rail behind, with overlay labels reading Cookie: stored in the browser and Session: stored on the server","sclblg987654321","school_blog_translations","\u003Cp>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.\u003C\u002Fp>\u003Cp>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.\u003C\u002Fp>\u003Ch2>Why does a website need help remembering you when HTTP remembers nothing?\u003C\u002Fh2>\u003Cp>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, \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc6265\">RFC 6265\u003C\u002Fa>, says so in its abstract: cookies let servers maintain a stateful session over the mostly stateless HTTP protocol.\u003C\u002Fp>\u003Cp>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.\u003C\u002Fp>\u003Ch2>What is the difference between a cookie and a session? A coat check and a claim ticket\u003C\u002Fh2>\u003Cp>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.\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>The Session\u003C\u002Fstrong> 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.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>The Cookie\u003C\u002Fstrong> 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.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>Two lines worth remembering:\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>Cookie: stored in the browser\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>Session: stored on the server\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>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.\u003C\u002Fp>\u003Cblockquote>\u003Cp>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.\u003C\u002Fp>\u003C\u002Fblockquote>\u003Ch2>Real headers: Set-Cookie and Cookie\u003C\u002Fh2>\u003Cp>The whole mechanism lives in just two headers. When the server wants the browser to hold a ticket, it sends a \u003Ccode>Set-Cookie\u003C\u002Fcode> header with the Response. From then on, every Request the browser makes to the same site automatically carries a \u003Ccode>Cookie\u003C\u002Fcode> header back.\u003C\u002Fp>\u003Cp>Our team ran \u003Ccode>curl\u003C\u002Fcode> against GitHub's login page on 29 September 2026 and got these headers back (the very long value is shortened):\u003C\u002Fp>\u003Cpre>\u003Ccode>set-cookie: _gh_sess=CV5197blwy...; path=\u002F; HttpOnly; secure; SameSite=Lax\nset-cookie: logged_in=no; expires=Wed, 29 Sep 2027 04:40:57 GMT; domain=.github.com; path=\u002F; HttpOnly; secure; SameSite=Lax\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>Notice that we had not logged in at all, yet GitHub had already issued a ticket, and \u003Ccode>logged_in=no\u003C\u002Fcode> says plainly that we are still a stranger. The first cookie, \u003Ccode>_gh_sess\u003C\u002Fcode>, has no \u003Ccode>expires\u003C\u002Fcode>. That detail matters, and we will explain why in the next section.\u003C\u002Fp>\u003Cp>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 \u003Ccode>curl\u003C\u002Fcode>. This is the actual output:\u003C\u002Fp>\u003Cpre>\u003Ccode>$ curl -i localhost:3456\u002Flogin\nSet-Cookie: sid=fdcada48136db79c388c5993fefcdc22; Path=\u002F; HttpOnly; Secure; SameSite=Lax\nlogged in\n\n$ curl localhost:3456\u002Fme\nwho are you?\n\n$ curl -H \"Cookie: sid=fdcada48136db79c388c5993fefcdc22\" localhost:3456\u002Fme\nhello somchai\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>The last line is the heart of it. The \u003Ccode>sid\u003C\u002Fcode> 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 \u003Ccode>Cookie\u003C\u002Fcode> 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.\u003C\u002Fp>\u003Ch2>The rules printed on the ticket: HttpOnly, Secure, SameSite, Expires\u003C\u002Fh2>\u003Cp>Everything after a \u003Ccode>;\u003C\u002Fcode> in \u003Ccode>Set-Cookie\u003C\u002Fcode> 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 \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FHTTP\u002FReference\u002FHeaders\u002FSet-Cookie\">MDN Set-Cookie reference\u003C\u002Fa>):\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>Expires \u002F Max-Age:\u003C\u002Fstrong> how long the ticket lives. \u003Ccode>Expires\u003C\u002Fcode> takes a date, \u003Ccode>Max-Age\u003C\u002Fcode> takes a number of seconds, and if both are set, \u003Ccode>Max-Age\u003C\u002Fcode> wins. If neither is set, the cookie becomes a session cookie that is removed when the browser shuts down. That is why GitHub's \u003Ccode>_gh_sess\u003C\u002Fcode> carries no expiry.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>HttpOnly:\u003C\u002Fstrong> JavaScript cannot read the cookie through \u003Ccode>document.cookie\u003C\u002Fcode>. 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 with \u003Ccode>fetch()\u003C\u002Fcode> requests as usual.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>Secure:\u003C\u002Fstrong> the cookie is only sent over \u003Ccode>https:\u003C\u002Fcode> (localhost excepted), so the ticket cannot leak on an unencrypted network.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>SameSite:\u003C\u002Fstrong> controls whether the cookie is sent with requests that come from another site. \u003Ccode>Strict\u003C\u002Fcode> sends it only for same-site requests, \u003Ccode>Lax\u003C\u002Fcode> also sends it when the user follows a link in from another site, and \u003Ccode>None\u003C\u002Fcode> sends it everywhere but must be paired with \u003Ccode>Secure\u003C\u002Fcode>. It helps protect against CSRF, where another site tricks your browser into sending a request on your behalf.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>The SameSite default deserves care. The \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.chromium.org\u002Fupdates\u002Fsame-site\u002F\">Chromium team announced\u003C\u002Fa> that from Chrome 80 onwards, cookies without a SameSite attribute are treated as \u003Ccode>SameSite=Lax\u003C\u002Fcode>. 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.\u003C\u002Fp>\u003Ch2>What about localStorage? Can it replace cookies?\u003C\u002Fh2>\u003Cp>Yes, and in many cases it is the better tool. \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FHTTP\u002FGuides\u002FCookies\">MDN itself recommends\u003C\u002Fa> the Web Storage API, \u003Ccode>localStorage\u003C\u002Fcode> and \u003Ccode>sessionStorage\u003C\u002Fcode>, 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. \u003Ccode>localStorage\u003C\u002Fcode> never goes to the server, and its data has no expiration time until something deletes it. Despite the name, \u003Ccode>sessionStorage\u003C\u002Fcode> 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.\u003C\u002Fp>\u003Cp>Things change when the data is a proof of identity. \u003Ccode>localStorage\u003C\u002Fcode> 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.\u003C\u002Fp>\u003Cp>Put simply: data that is not secret and that the server does not need can live in \u003Ccode>localStorage\u003C\u002Fcode>. For the ticket that says who you are, a cookie with the right attributes is still the standard choice.\u003C\u002Fp>\u003Ch2>JWT: the option without a coat rail\u003C\u002Fh2>\u003Cp>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 \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fen\u002Fblogs\u002Fwhat-is-jwt-token-explained\">What is a JWT token\u003C\u002Fa>. And if you want to see how a server responds when the ticket is missing or invalid, read about 401 in \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fen\u002Fblogs\u002Fhttp-status-codes-explained\">HTTP status codes explained\u003C\u002Fa>.\u003C\u002Fp>\u003Ch2>Is the \"accept cookies\" banner the same thing?\u003C\u002Fh2>\u003Cp>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 \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fen\u002Fblogs\u002Faccepting-cookies\">What is accepting cookies and why should you accept them\u003C\u002Fa>, so this article sticks to the mechanism.\u003C\u002Fp>\u003Cp>If you want the bigger picture of where a Session sits in a web system, \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fen\u002Fblogs\u002Fweb-development-front-end-back-end-full-stack\">Exploring the World of Web Development: Front End, Back End, and Full Stack\u003C\u002Fa> shows that the coat rail belongs on the Back End. And when you are ready to try it in Go, \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fen\u002Fblogs\u002Fgo-websocket-security-session-authentication\">Go and WebSocket Security\u003C\u002Fa> has an example of using Sessions for authentication.\u003C\u002Fp>\u003Cdiv data-type=\"horizontalRule\">\u003Chr>\u003C\u002Fdiv>\u003Ch2>Summary: what is the difference between a Cookie and a Session?\u003C\u002Fh2>\u003Cp>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.\u003C\u002Fp>\u003Cp>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 \u003Ccode>Set-Cookie\u003C\u002Fcode>, then check which \u003Ccode>Cookie\u003C\u002Fcode> the next Request sends back. Five minutes with the real thing teaches more than reading a definition ten times.\u003C\u002Fp>\u003Cp>Follow more articles and tips for people starting out as programmers on our channels.\u003C\u002Fp>\u003Cp>Facebook: \u003Cstrong>Superdev School (Superdev)\u003C\u002Fstrong> — \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.facebook.com\u002Fsuperdev.school.th\">https:\u002F\u002Fwww.facebook.com\u002Fsuperdev.school.th\u003C\u002Fa>\u003C\u002Fp>\u003Cp>Instagram: \u003Cstrong>superdevschool\u003C\u002Fstrong> — \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.instagram.com\u002Fsuperdevschool\u002F\">https:\u002F\u002Fwww.instagram.com\u002Fsuperdevschool\u002F\u003C\u002Fa>\u003C\u002Fp>\u003Cp>TikTok: \u003Cstrong>superdevschool\u003C\u002Fstrong> — \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.tiktok.com\u002F@superdevschool\">https:\u002F\u002Fwww.tiktok.com\u002F@superdevschool\u003C\u002Fa>\u003C\u002Fp>\u003Cp>Website: \u003Cstrong>www.superdevacademy.com\u003C\u002Fstrong> — \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002F\">https:\u002F\u002Fwww.superdevacademy.com\u002F\u003C\u002Fa>\u003C\u002Fp>","cover_cover_3beivrpvsc.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002Fq41bq3mi161ie6t\u002Fl\u002Fcover_cover_3beivrpvsc.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002Fq41bq3mi161ie6t\u002Fm\u002Fcover_cover_3beivrpvsc.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002Fq41bq3mi161ie6t\u002Fcover_cover_3beivrpvsc.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002Fq41bq3mi161ie6t\u002Fs\u002Fcover_cover_3beivrpvsc.webp","2026-09-29 04:47:46.856Z","wfztm6bp9384v3u",{"keywords":18,"locale":48,"school_blog":58},[19,25,29,33,36,40,44],{"collectionId":20,"collectionName":21,"created":22,"created_by":16,"id":23,"name":24,"updated":22,"updated_by":16},"sclkey987654321","school_keywords","2026-09-29 04:47:46.836Z","ibbf20ualzm2unl","cookie vs session",{"collectionId":20,"collectionName":21,"created":26,"created_by":16,"id":27,"name":28,"updated":26,"updated_by":16},"2026-09-29 04:47:46.837Z","3y5yshc03i564zq","what is a session",{"collectionId":20,"collectionName":21,"created":30,"created_by":16,"id":31,"name":32,"updated":30,"updated_by":16},"2026-09-29 04:46:20.215Z","u4w7npeduxukkuz","session cookie",{"collectionId":20,"collectionName":21,"created":30,"created_by":16,"id":34,"name":35,"updated":30,"updated_by":16},"6xx0oa2skxld2dq","httponly cookie",{"collectionId":20,"collectionName":21,"created":37,"created_by":16,"id":38,"name":39,"updated":37,"updated_by":16},"2026-09-29 04:46:20.216Z","stj7co03owu7fsy","localstorage vs cookie",{"collectionId":20,"collectionName":21,"created":41,"created_by":16,"id":42,"name":43,"updated":41,"updated_by":16},"2026-09-29 04:47:46.838Z","lgpmcrkcubnsi1t","set-cookie header",{"collectionId":20,"collectionName":21,"created":45,"created_by":16,"id":46,"name":47,"updated":45,"updated_by":16},"2026-09-29 04:47:46.839Z","zzde1ejhiii4ag9","samesite cookie",{"code":49,"collectionId":50,"collectionName":51,"created":52,"flag":53,"id":54,"is_default":55,"label":56,"updated":57},"en","pbc_1989393366","locales","2026-01-22 11:00:02.726Z","twemoji:flag-united-states","qv9c1llfov2d88z",false,"English","2026-04-10 15:42:46.825Z",{"category":59,"collectionId":60,"collectionName":61,"created":62,"expand":63,"id":80,"slug":81,"updated":82,"views":83},"rfxf19ot4iq992c","pbc_2105096300","school_blogs","2026-09-29 04:46:20.218Z",{"category":64},{"blogIds":65,"collectionId":66,"collectionName":67,"created":68,"created_by":69,"id":59,"image":70,"image_alt":71,"image_path":72,"image_s_url":73,"label":74,"name":75,"priority":76,"publish_at":77,"scheduled_at":71,"status":78,"updated":79,"updated_by":69},[],"sclcatblg987654321","school_category_blogs","2026-03-04 08:32:03.969Z","76qprkevbgfdps8","7acfigk1qkd_lv1k6bkji3_7h89h9h63a.webp","","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclcatblg987654321\u002Frfxf19ot4iq992c\u002F7acfigk1qkd_lv1k6bkji3_7h89h9h63a.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclcatblg987654321\u002Frfxf19ot4iq992c\u002Fs\u002F7acfigk1qkd_lv1k6bkji3_7h89h9h63a.webp",{"en":75,"th":75},"Web Development",0,"2025-01-21 03:43:00.282Z","published","2026-08-18 14:48:42.218Z","rnj71f99yfx3r2p","cookie-vs-session-explained","2026-10-07 10:10:02.849Z",103,"q41bq3mi161ie6t",[23,27,31,34,38,42,46],"2026-10-07 10:10:03.592Z","Cookie vs session explained with real Set-Cookie headers: the data lives on the server, the browser only holds a ticket. Plus HttpOnly, Secure and SameSite.","Cookie vs Session: How Websites Remember You Are Logged In","2026-10-07 10:10:03.595Z","ebkf8ra4nd55ual",1,{"th":81,"en":81},[94,98,102,106,110,114],{"answer":95,"id":96,"question":97},"A cookie is a small piece of data the browser stores and sends back in the Cookie header with every request, while a session is the user's data kept on the server. They usually work together: the server sends a Set-Cookie header containing a Session ID, the browser holds it like a claim ticket, and the server uses that ticket to look up the right session on each later request.","j0o66cz2nj9e74k","What is the difference between a cookie and a session?",{"answer":99,"id":100,"question":101},"A session cookie is a cookie sent without an Expires or Max-Age attribute, and according to MDN it is removed when the browser shuts down. A cookie with Expires set to a date, or Max-Age set to a number of seconds, survives until that time even after the browser closes. If both are set, Max-Age takes precedence. GitHub's _gh_sess cookie, for example, is sent with no expiry.","hsv4ccutycrf6ij","What is a session cookie, and how is it different from a persistent cookie?",{"answer":103,"id":104,"question":105},"A session has expired when the server no longer recognises the Session ID the browser sends. Either the server deleted the session data after a period of inactivity it defines itself, or the cookie holding the Session ID reached its Expires or Max-Age limit. Either way, the next request looks like a stranger, so the site sends you back to the login page. Each site sets its own timeout; there is no standard figure.","pqtrjatqz0hk4is","What does it mean when a session expires, and why do I have to log in again?",{"answer":107,"id":108,"question":109},"HttpOnly is a Set-Cookie attribute that stops JavaScript from reading the cookie through document.cookie, so a malicious script injected through XSS cannot steal the Session ID. The browser still attaches the cookie to normal requests, including those made with fetch(). MDN describes HttpOnly as mitigating XSS rather than preventing every attack, so it should be combined with the Secure and SameSite attributes.","5b3w11nq9bcojbh","What is an HttpOnly cookie and how does it improve security?",{"answer":111,"id":112,"question":113},"localStorage keeps data in the browser without ever sending it to the server, and the data has no expiration time until it is deleted. Cookies are attached to every request to their site and can be given a lifetime with Expires or Max-Age. MDN recommends localStorage for general client-side data such as a chosen theme, but any JavaScript on the page can read localStorage, so it has no protection like the HttpOnly flag on cookies.","df8d2ut1p93dp61","What is the difference between localStorage and cookies?",{"answer":115,"id":116,"question":117},"RFC 6265 says general-use browsers should support at least 4096 bytes per cookie, counting the name, value and attributes together, plus at least 50 cookies per domain and 3000 cookies in total. These are minimums browsers should provide, not a ceiling every browser shares. The same RFC advises servers to use as few and as small cookies as possible, because the Cookie header is sent with every request.","1pte0wdwpway1ox","What is the maximum size of a cookie?"]