Cookie parser
A cookie that "does not get set" is almost always a rule violation the browser applied without telling you: SameSite=None without Secure, a __Host- prefix with a Domain attribute, an Expires date already in the past. Paste the header and every attribute is laid out, with the violations named.
Cookies
Issues
Summary
How to use
- Paste either form. A
Cookie:request header packs every cookie onto one line with no attributes;Set-Cookie:is one cookie per line with attributes. The tool works out which you pasted and says so in the summary. - Read the table. Percent-encoded values are shown both raw and decoded, since
theme%3Ddarkandtheme=darklook very different when you are debugging. - Issues lists rule violations and risky configurations, each with what the browser will actually do about it.
- The Summary totals the byte size — worth watching, because every cookie for a host is sent on every single request to it.
The rules browsers enforce without a warning
SameSite=None requires Secure. Without it the cookie is rejected outright — not downgraded, rejected. This is the most common cause of a third-party or cross-site cookie that never appears, and it produces no console error in most browsers.
No SameSite means Lax. Since 2020 an unspecified SameSite is treated as Lax, so the cookie is not sent on cross-site POSTs, iframes, or fetches. Code written before that change and never touched since often breaks in exactly one flow — usually a payment callback or an SSO POST — because that is the only cross-site POST in the app.
__Host- and __Secure- prefixes are enforced. A cookie named __Secure-x must have Secure. A cookie named __Host-x must have Secure, must have Path=/, and must have no Domain attribute at all. Break any of those and the browser drops the cookie silently. They are worth using — __Host- in particular makes a cookie impossible for a subdomain to overwrite, which defeats session-fixation via a compromised subdomain.
A leading dot in Domain does nothing. Domain=.example.com and Domain=example.com are identical to modern browsers: both include subdomains. Omitting Domain entirely is the restrictive option — a host-only cookie, which is what you usually want.
Expires in the past deletes the cookie. That is the standard way to remove one, so it is only a bug if you did not mean it. Max-Age takes precedence over Expires where both are present, and Max-Age=0 also deletes.
Size limits are real. A single cookie above roughly 4 096 bytes is dropped. Servers also cap total header size — nginx defaults to 8 KB for the whole request — so a large cookie jar produces a 400 Request Header Or Cookie Too Large that looks like a server fault.
Session cookies need HttpOnly and Secure. Without HttpOnly any injected script can read the session; without Secure it travels over plain HTTP. Cookies whose names look session-like are checked for both.
FAQ
Where do I get a Set-Cookie header to paste?
DevTools → Network → the request → Response Headers, or curl -sI https://example.com. The Application → Cookies panel shows the stored result instead, which is also useful but does not show you what the server sent.
Does it validate the cookie against a domain?
No — it checks the header's internal consistency and the prefix rules, which do not depend on the request URL. Whether a Domain value is permitted depends on the origin that set it, and on the Public Suffix List: a site cannot set a cookie for .co.uk. The domain extractor can tell you where the public suffix boundary is.
What is Partitioned / CHIPS?
A newer attribute that scopes a third-party cookie to the top-level site that embedded it, so an embed on two different sites gets two separate cookies. It is reported in the "Other" column when present. It requires Secure and Path=/.
Are cookie names case-sensitive?
Names and values are; attribute names are not. Two cookies differing only in the case of their name are two different cookies, which is an unpleasant bug to track down.