The Set-Cookie
HTTP response header is used to send a cookie from the server to the user agent, so the user agent can send it back to the server later. To send multiple cookies, multiple Set-Cookie
headers should be sent in the same response.
Browsers block frontend JavaScript code from accessing the Set Cookie
header, as required by the Fetch spec, which defines Set-Cookie
as a forbidden response-header name that must be filtered out from any response exposed to frontend code.
For more information, see the guide on HTTP cookies.
Header type | Response header |
---|---|
Forbidden header name | no |
Forbidden response-header name | yes |
Syntax
Set-Cookie: <cookie-name>=<cookie-value> Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date> Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit> Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value> Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value> Set-Cookie: <cookie-name>=<cookie-value>; Secure Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax Set-Cookie: <cookie-name>=<cookie-value>; SameSite=None // Multiple attributes are also possible, for example: Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
Attributes
<cookie-name>=<cookie-value>
- A cookie begins with a name-value pair:
- A
<cookie-name>
can be any US-ASCII characters, except control characters, spaces, or tabs. It also must not contain a separator character like the following:( ) < > @ , ; : \ " / [ ] ? = { }
. - A
<cookie-value>
can optionally be wrapped in double quotes and include any US-ASCII characters excluding control characters, Whitespace, double quotes, comma, semicolon, and backslash. Encoding: Many implementations perform URL encoding on cookie values, however it is not required per the RFC specification. It does help satisfying the requirements about which characters are allowed for <cookie-value> though. __Secure-
prefix: Cookies names starting with__Secure-
(dash is part of the prefix) must be set with thesecure
flag from a secure page (HTTPS).__Host-
prefix: Cookies with names starting with__Host-
must be set with thesecure
flag, must be from a secure page (HTTPS), must not have a domain specified (and therefore aren't sent to subdomains) and the path must be/
.
- A
Expires=<date>
Optional-
The maximum lifetime of the cookie as an HTTP-date timestamp. See
Date
for the required formatting.If unspecified, the cookie becomes a session cookie. A session finishes when the client shuts down, and session cookies will be removed.
Warning: Many web browsers have a session restore feature that will save all tabs and restore them next time the browser is used. Session cookies will also be restored, as if the browser was never closed.
When an Expires date is set, the deadline is relative to the client the cookie is being set on, not the server.
Max-Age=<number>
Optional- Number of seconds until the cookie expires. A zero or negative number will expire the cookie immediately. If both
Expires
andMax-Age
are set,Max-Age
has precedence. Domain=<domain-value>
Optional- Host to which the cookie will be sent.
- If omitted, defaults to the host of the current document URL, not including subdomains.
- Contrary to earlier specifications, leading dots in domain names (
.example.com
) are ignored. - Multiple host/domain values are not allowed, but if a domain is specified, then subdomains are always included.
Path=<path-value>
Optional- A path that must exist in the requested URL, or the browser won't send the
Cookie
header. - The forward slash (
/
) character is interpreted as a directory separator, and subdirectories will be matched as well: forPath=/docs
,/docs
,/docs/Web/
, and/docs/Web/HTTP
will all match. Secure
Optional- A secure cookie is only sent to the server when a request is made with the
https:
scheme. (However, confidential information should never be stored in HTTP Cookies, as the entire mechanism is inherently insecure and doesn't encrypt any information.)Note: Insecure sites (
http:
) can't set cookies with theSecure
attribute (since Chrome 52 and Firefox 52). HttpOnly
Optional- Forbids JavaScript from accessing the cookie, for example, through the
Document.cookie
property. Note that a cookie that has been created with HttpOnly will still be sent with JavaScript-initiated requests, e.g. when callingXMLHttpRequest.send()
orfetch()
. This mitigates attacks against cross-site scripting (XSS). SameSite=<samesite-value>
Optional-
Strict
: The browser sends the cookie only for same-site requests (that is, requests originating from the same site that set the cookie). If the request originated from a different URL than the current one, no cookies with theSameSite=Strict
attribute are sent.Lax
: The cookie is withheld on cross-site subrequests, such as calls to load images or frames, but is sent when a user navigates to the URL from an external site, such as by following a link.None
: The browser sends the cookie with both cross-site and same-site requests.
Asserts that a cookie must not be sent with cross-origin requests, providing some protection against cross-site request forgery attacks (CSRF).
Browsers are migrating to have cookies default to
SameSite=Lax
. If a cookie is needed to be sent cross-origin, opt out of theSameSite
restriction using theNone
value. TheNone
value requires theSecure
attribute.
Examples
Session cookie
Session cookies are removed when the client shuts down. Cookies are session cookies if they don't specify the Expires
or Max-Age
attributes.
Set-Cookie: sessionId=38afes7a8
Permanent cookie
Instead of expiring when the client is closed, permanent cookies expire at a specific date (Expires
) or after a specific length of time (Max-Age
).
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT
Set-Cookie: id=a3fWa; Max-Age=2592000
Invalid domains
A cookie for a domain that does not include the server that set it should be rejected by the user agent.
The following cookie will be rejected if set by a server hosted on originalcompany.com
:
Set-Cookie: qwerty=219ffwef9w0f; Domain=somecompany.co.uk
A cookie for a sub domain of the serving domain will be rejected.
The following cookie will be rejected if set by a server hosted on example.com
:
Set-Cookie: sessionId=e8bb43229de9; Domain=foo.example.com
Cookie prefixes
Cookies names prefixed with __Secure-
or __Host-
can be used only if they are set with the secure
attribute from a secure (HTTPS) origin.
In addition, cookies with the __Host-
prefix must have a path of /
(meaning any path at the host) and must not have a Domain
attribute.
For clients that don't implement cookie prefixes, you cannot count on these additional assurances, and prefixed cookies will always be accepted.
// Both accepted when from a secure origin (HTTPS) Set-Cookie: __Secure-ID=123; Secure; Domain=example.com Set-Cookie: __Host-ID=123; Secure; Path=/ // Rejected due to missing Secure attribute Set-Cookie: __Secure-id=1 // Rejected due to the missing Path=/ attribute Set-Cookie: __Host-id=1; Secure // Rejected due to setting a Domain Set-Cookie: __Host-id=1; Secure; Path=/; Domain=example.com
Specifications
Specification | Title |
---|---|
RFC 6265, section 4.1: Set-Cookie | HTTP State Management Mechanism |
draft-ietf-httpbis-rfc6265bis-05 | Cookie Prefixes, Same-Site Cookies, and Strict Secure Cookies |
Browser compatibility
The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.
Desktop | Mobile | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Set-Cookie | Chrome Full support Yes | Edge Full support 12 | Firefox Full support Yes | IE Full support Yes | Opera Full support Yes | Safari Full support Yes | WebView Android Full support Yes | Chrome Android Full support Yes | Firefox Android Full support Yes | Opera Android Full support Yes | Safari iOS Full support Yes | Samsung Internet Android Full support Yes |
HttpOnly | Chrome Full support 1 | Edge Full support 12 | Firefox Full support 3 | IE Full support 9 | Opera Full support 11 | Safari Full support 5 | WebView Android Full support 37 | Chrome Android Full support Yes | Firefox Android Full support 4 | Opera Android Full support Yes | Safari iOS Full support 4 | Samsung Internet Android Full support Yes |
Max-Age | Chrome Full support Yes | Edge Full support 12 | Firefox Full support Yes | IE Full support 8 | Opera Full support Yes | Safari Full support Yes | WebView Android Full support Yes | Chrome Android Full support Yes | Firefox Android Full support Yes | Opera Android Full support Yes | Safari iOS Full support Yes | Samsung Internet Android Full support Yes |
SameSite | Chrome Full support 51 | Edge Full support 16 | Firefox Full support 60 | IE No support No | Opera Full support 39 | Safari
Full support
13
| WebView Android Full support 51 | Chrome Android Full support 51 | Firefox Android Full support 60 | Opera Android Full support 41 | Safari iOS
Full support
13
| Samsung Internet Android Full support 5.0 |
SameSite : SameSite=Lax | Chrome Full support 51 | Edge Full support 16 | Firefox Full support 60 | IE No support No | Opera Full support 39 | Safari Full support 12 | WebView Android Full support 51 | Chrome Android Full support 51 | Firefox Android Full support 60 | Opera Android Full support 41 | Safari iOS Full support 12.2 | Samsung Internet Android Full support 5.0 |
SameSite : Defaults to Lax | Chrome Full support 80 | Edge Full support 80 | Firefox
Full support
69
| IE No support No | Opera Full support 67 | Safari No support No | WebView Android Full support 80 | Chrome Android Full support 80 | Firefox Android No support No | Opera Android No support No | Safari iOS No support No | Samsung Internet Android No support No |
SameSite : SameSite=None | Chrome Full support 51 | Edge Full support 16 | Firefox Full support 60 | IE No support No | Opera Full support 39 | Safari
Full support
13
| WebView Android Full support 51 | Chrome Android Full support 51 | Firefox Android Full support 60 | Opera Android Full support 41 | Safari iOS Full support 13 | Samsung Internet Android Full support 5.0 |
SameSite : SameSite=Strict | Chrome Full support 51 | Edge Full support 16 | Firefox Full support 60 | IE No support No | Opera Full support 39 | Safari Full support 12 | WebView Android Full support 51 | Chrome Android Full support 51 | Firefox Android Full support 60 | Opera Android Full support 41 | Safari iOS Full support 12.2 | Samsung Internet Android Full support 5.0 |
SameSite : Secure context required | Chrome Full support 80 | Edge Full support 80 | Firefox
Full support
69
| IE No support No | Opera Full support 67 | Safari No support No | WebView Android Full support 80 | Chrome Android Full support 80 | Firefox Android No support No | Opera Android No support No | Safari iOS No support No | Samsung Internet Android No support No |
Cookie prefixes | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 50 | IE No support No | Opera Full support 36 | Safari Full support Yes | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 50 | Opera Android Full support 36 | Safari iOS Full support Yes | Samsung Internet Android Full support 5.0 |
Legend
- Full support
- Full support
- No support
- No support
- See implementation notes.
- See implementation notes.
- User must explicitly enable this feature.
- User must explicitly enable this feature.
Compatibility notes
- Starting with Chrome 52 and Firefox 52, insecure sites (
http:
) can't set cookies with theSecure
attribute anymore.