A cookie is a small piece of data that a web server stores in the user’s browser and that the browser automatically sends back to that server on subsequent requests. Because HTTP is stateless, cookies are the primary mechanism that lets a site remember who you are across requests, powering login sessions, shopping carts, and preferences. A cookie is a name-value pair accompanied by attributes that control its lifetime, scope, and security, and understanding those attributes is essential to using cookies safely.
Key takeaways
- Cookies give stateless HTTP a way to remember state across requests.
- A server sets them with
Set-Cookie; the browser returns them in theCookieheader. - Attributes like
Expires,Domain, andPathcontrol lifetime and scope. HttpOnly,Secure, andSameSiteare the core security flags.- Cookies are sent on every matching request, so keep them small.
- They are scoped by domain and path, so unrelated sites cannot read each other’s cookies.
How are cookies set and sent?
The server creates a cookie by including a Set-Cookie header in its response:
Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax
The browser stores it and, on every later request to a matching domain and path, sends it back:
Cookie: session_id=abc123
This round trip happens automatically for every request the browser makes to that site, including images and API calls, which is why cookies are so convenient for sessions and also why keeping them small matters for performance.
What attributes can a cookie have?
The name-value pair is followed by optional attributes that govern behavior. Getting these right is the difference between a secure cookie and a liability.
| Attribute | Purpose |
|---|---|
Expires / Max-Age |
Sets a lifetime; without either, the cookie lasts only for the session |
Domain |
Which host(s) the cookie is sent to |
Path |
Which URL paths the cookie applies to |
Secure |
Send only over HTTPS |
HttpOnly |
Hide from JavaScript |
SameSite |
Control sending on cross-site requests |
If you omit Expires and Max-Age, the cookie is a session cookie and is discarded when the browser closes. Adding either makes it persistent, surviving until the specified time.
The Domain and Path attributes define scope: exactly which requests carry the cookie. If you set Domain=example.com the cookie is sent to that host and its subdomains, whereas omitting Domain limits it to the exact host that set it, which is usually the safer choice. Path=/admin restricts the cookie to URLs under that path. Scope is a security boundary, not just a convenience: a cookie scoped too broadly is exposed to more of your site than it needs to be, so scope every cookie as narrowly as the feature allows. A useful hardening technique is the cookie name prefix. A name beginning with __Host- is only accepted by the browser when the cookie is Secure, has no Domain, and uses a path of /, which prevents a subdomain from overwriting it and locks the cookie to a single origin.
How do the security flags protect cookies?
Three flags do most of the security work, and every session cookie should use them deliberately.
HttpOnly
Marking a cookie HttpOnly makes it unreadable from JavaScript’s document.cookie. This is critical for session tokens because it means a cross-site scripting (XSS) flaw cannot simply read and exfiltrate the session.
Secure
The Secure flag ensures the cookie is only ever sent over HTTPS, preventing it from leaking over an unencrypted connection where it could be intercepted.
SameSite
The SameSite attribute controls whether the cookie rides along on requests originating from other sites, which is the main defense against cross-site request forgery (CSRF).
Strict— never sent on cross-site requests.Lax— sent on top-level navigations but not on cross-site subrequests; a sensible default.None— sent on all cross-site requests, but browsers requireSecurealongside it.
How do I read and write cookies in JavaScript?
Client-side, cookies are accessed through document.cookie, though only cookies without the HttpOnly flag are visible:
// Write a cookie
document.cookie = "theme=dark; path=/; max-age=2592000";
// Read all readable cookies as one string
const raw = document.cookie;
The API is awkward: reading returns every readable cookie in a single semicolon-separated string that you must parse yourself, and writing one cookie does not overwrite the whole string. For anything security-sensitive, set cookies from the server with HttpOnly so client scripts cannot touch them at all.
How do cookies power authentication sessions?
The most important use of cookies is keeping a user logged in. The typical flow ties a cookie to server-side session state:
- The user submits credentials, and the server verifies them.
- The server creates a session record and sends a cookie holding an unguessable session identifier, marked
HttpOnly,Secure, and with a suitableSameSitevalue. - On each later request the browser returns the cookie, and the server looks up the session to know who the user is.
- On logout the server invalidates the session and the cookie is cleared.
The key design principle is that the cookie should carry a reference to server-side state, not the sensitive data itself. Storing a raw user identifier or role in a plain cookie is dangerous because the client can tamper with it; either keep the trusted data on the server keyed by the session id, or sign the cookie so tampering is detectable. This is also why session cookies must be treated as secrets: anyone who obtains one can impersonate the user until it expires, so short lifetimes and the security flags above matter directly.
What is the difference between cookies and other browser storage?
Cookies are one of several ways to persist data in the browser, and choosing the wrong one causes bloat or security problems.
| Mechanism | Sent to server? | Typical size | Best for |
|---|---|---|---|
| Cookie | Yes, every request | Small (a few KB) | Sessions, auth tokens |
| Local storage | No | Larger | Client-only preferences |
| Session storage | No | Larger | Per-tab temporary data |
The defining trait of a cookie is that it is transmitted to the server automatically. That is exactly what you want for authentication and exactly what you do not want for large client-only data, which belongs in local or session storage instead.
A distinction you will encounter is first-party versus third-party cookies. A first-party cookie belongs to the site shown in the address bar; a third-party cookie is set by a different domain embedded in the page, such as an advertisement or an analytics widget, and has historically been used to track users across sites. Browsers have moved steadily to restrict third-party cookies, and the stricter SameSite defaults are part of that shift. For your own application this means you should not depend on third-party cookie behavior, and you should design features around first-party cookies that stay within your own origin.
What are common cookie mistakes and privacy considerations?
- Storing sensitive data in the value. Cookies can be read or tampered with unless signed or encrypted server-side; never put raw secrets or trust-sensitive values in them unprotected.
- Forgetting security flags. A session cookie without
HttpOnly,Secure, and a sensibleSameSiteis exposed to XSS, interception, and CSRF. - Oversized cookies. Because they travel on every request, large cookies slow down the whole site.
- Overbroad domain or path. Setting a wide
Domaincan leak a cookie to subdomains that should not see it. - Ignoring consent rules. Non-essential cookies, such as tracking cookies, are subject to privacy regulations that require user consent in many jurisdictions.
Frequently asked questions
How is a cookie set?
A server sets a cookie by sending a Set-Cookie response header, and the browser stores it and returns it on subsequent requests to that domain via the Cookie header. JavaScript can also set non-HttpOnly cookies.
What is the difference between a session cookie and a persistent cookie?
A session cookie has no expiry and is deleted when the browser closes; a persistent cookie has an Expires or Max-Age attribute and survives until that time passes.
What does the HttpOnly flag do?
HttpOnly prevents JavaScript from reading the cookie via document.cookie, which protects session tokens from being stolen through cross-site scripting attacks.
What is the difference between cookies and local storage?
Cookies are sent to the server on every matching request and have size limits and security flags; local storage stays in the browser, is not sent automatically, and holds more data.
What does the SameSite attribute do?
SameSite controls whether a cookie is sent on cross-site requests, which is a key defense against cross-site request forgery. Common values are Lax, Strict, and None.
Why must Secure be set for cross-site cookies?
A cookie with SameSite=None is sent in cross-site contexts, so browsers require the Secure flag to ensure it is only transmitted over HTTPS and not exposed on plain connections.
Can one site read another site’s cookies?
No. Cookies are scoped by domain and path, and the same-origin and SameSite rules prevent an unrelated site from reading cookies that were set for a different domain.