A cookie generator for correct, secure Set-Cookie headers
This cookie generator builds a Set-Cookie header from simple fields — name, value, lifetime, Domain, Path, Secure, HttpOnly, SameSite, Partitioned and Priority — and checks it against the rules browsers actually enforce. Alongside the raw header it writes the equivalent code for Express, PHP, Python (Flask or Django), Nginx, Apache and document.cookie, so you can paste the result straight into your app or server config.
Small mistakes make browsers drop cookies without any error message: SameSite=None without Secure, a __Host- cookie with a Domain, a lifetime longer than 400 days, an unencoded semicolon in the value or a cookie over 4 KB. The generator flags each one as you type and explains the fix. A built-in test then sets the cookie on this page and shows exactly what your browser stored.
How to use the Cookie Generator
- Pick a Name prefix (the
__Host-default is the safest choice for session cookies), then enter the Name, Path and Value. Keep “URL-encode the value” ticked unless the value is already safe. - Choose a Lifetime: a session cookie, a Max-Age in seconds to days, a fixed Expires date in your time zone, or a header that deletes the cookie.
- Leave Domain empty to keep the cookie on one host, choose SameSite, and tick Secure, HttpOnly or Partitioned as needed.
- Read the findings under the header — red items will make browsers reject the cookie.
- Select a code tab (HTTP, JavaScript, Express, PHP, Python, Nginx or Apache) and press Copy code.
- Press Set test cookie to see what the browser keeps, then Remove test cookie.
Cookie Generator features
Rules browsers enforce
Checks name characters, value encoding, the 4,096-byte limit, 1,024-byte attribute values, __Secure- and __Host- prefixes, SameSite=None plus Secure, Partitioned plus Secure and the 400-day lifetime cap.
Seven output formats
Raw header, document.cookie, Express res.cookie, PHP 7.3+ setcookie options array, Flask/Werkzeug set_cookie, Nginx add_header and Apache Header always add.
Correct units everywhere
Max-Age in seconds for the header and Python, milliseconds for Express, time() + n for PHP, and an IMF-fixdate such as “Tue, 15 Jan 2030 12:00:00 GMT” for Expires.
Live browser test
Sets the cookie with document.cookie, reads it back through the Cookie Store API where available, and explains why a cookie was refused.
Random session IDs
One click creates a 192-bit random value with crypto.getRandomValues, encoded as URL-safe Base64.
Recommended settings by cookie type
| Cookie | Suggested header |
|---|---|
| Login session | __Host-sid=…; Path=/; Secure; HttpOnly; SameSite=Lax (no Max-Age: ends with the browser session) |
| “Remember me” | __Host-remember=…; Max-Age=2592000; Path=/; Secure; HttpOnly; SameSite=Lax |
| UI preference | theme=dark; Max-Age=31536000; Path=/; Secure; SameSite=Lax (readable by scripts) |
| Embedded widget (third-party) | __Host-widget=…; Path=/; Secure; HttpOnly; SameSite=None; Partitioned |
| Delete a cookie | sid=; Max-Age=0; Path=/; Secure with the same Path and Domain as before |
Worked example: from fields to header
Name theme, value dark mode, Max-Age 30 days, Path /, Secure and SameSite Lax give Set-Cookie: theme=dark%20mode; Max-Age=2592000; Path=/; Secure; SameSite=Lax. The space is percent-encoded because a raw space is not allowed in a cookie value, and 30 days becomes 30 × 86,400 = 2,592,000 seconds.
In Express the same cookie is res.cookie('theme', 'dark mode', { maxAge: 2592000000, path: '/', secure: true, sameSite: 'lax' }) — milliseconds, and the value unencoded because Express encodes it. To check a header you already have, paste it into the Cookie Decoder; values can be encoded by hand with the URL Encoder.
Cookies are one layer of defence
HttpOnly hides a session cookie from injected scripts, but it does not stop those scripts acting on the page. Pair it with a strict Content-Security-Policy from the CSP Generator, and use unpredictable session IDs — the Random String Generator or the Random ID button here — rather than user names or counters.
Cookie Generator FAQ
How do I create a secure cookie?
Use the cookie generator’s default: the __Host- prefix, Path=/, no Domain, Secure, HttpOnly and SameSite=Lax. That combination keeps the cookie on one host, sends it only over HTTPS, hides it from JavaScript and stops it riding along on most cross-site requests.
Should I use Max-Age or Expires?
Max-Age, a number of seconds, is simpler and unaffected by clock differences, and it wins whenever both are present. Expires, an absolute date, is only needed for very old browsers such as Internet Explorer 8, which ignored Max-Age.
Why can’t JavaScript set an HttpOnly cookie?
HttpOnly exists to keep cookies away from scripts, so browsers ignore document.cookie writes that include it. Only a Set-Cookie header in a server response can create an HttpOnly cookie — which is why the browser test here leaves the flag out.
What does the Partitioned attribute do?
It opts a third-party cookie into CHIPS (Cookies Having Independent Partitioned State): the browser keeps a separate copy for each top-level site that embeds you, so the cookie works in an embed without enabling cross-site tracking. It must be Secure.
How long can a cookie last?
Browsers that follow the updated cookie standard (RFC 6265bis), including Chrome, cap Expires and Max-Age at 400 days. Longer values are silently shortened, so “remember me” cookies need refreshing.
Is the test cookie sent anywhere?
It is stored for this site in your browser and, like any cookie, attached to later requests to this site, which does not read it. Press Remove test cookie to delete it straight away.