Set-Cookie
response headerauthentication & cookies
Stores a cookie in the browser, with attributes that control its lifetime, scope and security.
Each Set-Cookie header stores one cookie; send several headers to set several cookies. The attributes after the name and value decide how long the cookie lives, which requests carry it, and whether JavaScript can read it. For session cookies, the safe baseline is HttpOnly; Secure; SameSite=Lax.
Syntax
Set-Cookie: <name>=<value>[; <attribute>]…
Defined in RFC 6265 §4.1 — Set-Cookie.
Values
| Max-Age=<seconds> | lifetime in seconds; 0 deletes the cookie |
|---|---|
| Expires=<date> | expiry as an HTTP date; Max-Age wins if both are set |
| HttpOnly | hidden from document.cookie, so XSS can't steal it |
| Secure | only sent over HTTPS |
| SameSite=Lax | not sent on cross-site subrequests; sent when following a link (the browser default) |
| SameSite=Strict | never sent on cross-site requests |
| SameSite=None | sent cross-site too — requires Secure |
| Domain=<domain> | also send to subdomains; omit to keep it host-only |
| Path=<path> | only send for URLs under this path |
Examples
Set-Cookie: session=abc123; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=604800
a secure one-week session cookie
Set-Cookie: session=; Path=/; Max-Age=0
delete a cookie — Path and Domain must match the original
Set-Cookie: __Host-session=abc123; Path=/; Secure; HttpOnly; SameSite=Strict
the __Host- prefix makes browsers enforce Secure, Path=/ and no Domain
Good to know
- Without Max-Age or Expires, a cookie lasts for the browser session — though browsers that restore tabs may keep it.
- Deleting a cookie only works with the same Path and Domain it was set with.
- Browsers cap cookies at about 4 KB each — store an id, not data.
- Cross-site cookies need
SameSite=None; Secure, and many browsers block third-party cookies regardless.
Further reading: SameSite cookies explained
How to set Set-Cookie
res.cookie("session", token, {
httpOnly: true,
secure: true,
sameSite: "lax",
maxAge: 7 * 24 * 60 * 60 * 1000, // milliseconds in Express
});import { cookies } from "next/headers";
(await cookies()).set("session", token, {
httpOnly: true,
secure: true,
sameSite: "lax",
maxAge: 60 * 60 * 24 * 7, // seconds
});resp.set_cookie(
"session", token,
httponly=True, secure=True, samesite="Lax",
max_age=60 * 60 * 24 * 7,
)http.SetCookie(w, &http.Cookie{
Name: "session",
Value: token,
Path: "/",
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteLaxMode,
MaxAge: 7 * 24 * 60 * 60,
})Check it
Fetch only the response headers and filter for Set-Cookie. In the browser, it's under Response Headers in DevTools → Network.
curl -sI https://example.com/ | grep -i '^set-cookie:'
To compare response headers across many URLs at once, use the HTTP Status Checker.
Frequently asked questions
Why isn't my cookie being saved?
Common causes: Secure on a plain-HTTP origin (localhost is the exception in most browsers), SameSite=None without Secure, a Domain that doesn't match the site, or a cross-origin fetch without credentials: 'include'.
Can I set several cookies in one Set-Cookie header?
No. Unlike most headers, Set-Cookie can't be comma-joined; send one header per cookie.