


13 Answers 13


this one's a quickie:

You might think it should be, but really it's not at all!

What are the allowed characters in both cookie name and value?

According to the ancient Netscape cookie_spec the entire NAME=VALUE string is:



By implication of the above:

  • = is legal to include, but potentially ambiguous. Browsers always split the name and value on the first = symbol in the string, so in practice you can put an = symbol in the VALUE but not the NAME.

What isn't mentioned, because Netscape were terrible at writing specs, but seems to be consistently supported by browsers:

  • either the NAME or the VALUE may be empty strings

  • if there is no = symbol in the string at all, browsers treat it as the cookie with the empty-string name, ie Set-Cookie: foo is the same as Set-Cookie: =foo.

  • when browsers output a cookie with an empty name, they omit the equals sign. So Set-Cookie: =bar begets Cookie: bar.

  • commas and spaces in names and values do actually seem to work, though spaces around the equals sign are trimmed

  • control characters (\x00 to \x1F plus \x7F) aren't allowed

What isn't mentioned and browsers are totally inconsistent about, is non-ASCII (Unicode) characters:

  • in Opera and Google Chrome, they are encoded to Cookie headers with UTF-8;

so in practice you cannot use non-ASCII characters in cookies at all. If you want to use Unicode, control codes or other arbitrary byte sequences, the cookie_spec demands you use an ad-hoc encoding scheme of your own choosing and suggest URL-encoding (as produced by JavaScript's encodeURIComponent) as a reasonable choice.

In terms of actual standards, there have been a few attempts to codify cookie behaviour but none thus far actually reflect the real world.

  • RFC 2109 was an attempt to codify and fix the original Netscape cookie_spec. In this standard many more special characters are disallowed, as it uses RFC 2616 tokens (a - is still allowed there), and only the value may be specified in a quoted-string with other characters. No browser ever implemented the limitations, the special handling of quoted strings and escaping, or the new features in this spec.

  • RFC 2965 was another go at it, tidying up 2109 and adding more features under a ‘version 2 cookies’ scheme. Nobody ever implemented any of that either. This spec has the same token-and-quoted-string limitations as the earlier version and it's just as much a load of nonsense.

  • RFC 6265 is an HTML5-era attempt to clear up the historical mess. It still doesn't match reality exactly but it's much better then the earlier attempts—it is at least a proper subset of what browsers support, not introducing any syntax that is supposed to work but doesn't (like the previous quoted-string).

In 6265 the cookie name is still specified as an RFC 2616 token, which means you can pick from the alphanums plus:


In the cookie value it formally bans the (filtered by browsers) control characters and (inconsistently-implemented) non-ASCII characters. It retains cookie_spec's prohibition on space, comma and semicolon, plus for compatibility with any poor idiots who actually implemented the earlier RFCs it also banned backslash and quotes, other than quotes wrapping the whole value (but in that case the quotes are still considered part of the value, not an encoding scheme). So that leaves you with the alphanums plus:


In the real world we are still using the original-and-worst Netscape cookie_spec, so code that consumes cookies should be prepared to encounter pretty much anything, but for code that produces cookies it is advisable to stick with the subset in RFC 6265.

| improve this answer | |
  • 1
  • 2
    RFC 6265 defines token as 1*<any CHAR except CTLs or separators> and separators are (, ), <, >, @, ,, ;, :, \, ", /, [, ], ?, =, {, }, SP and HT, so cookie names should be alphanums plus !#$%&'*+-.?^_`|~ – Gan Quan Aug 5 '19 at 22:47


// Encode

// Decode


| improve this answer | |


| improve this answer | |
  • This answer seems to be the consistent one across browsers. I realised this after working many hours trying to get a quick solution: I did not get one either. Just do as recommended exactly above to save yourself the hassles. – smile Mar 11 '18 at 18:02
  • Didn't try this, but I read other posts about this saying that base64 encode only works with ascii characters. – user984003 Sep 7 '19 at 15:29

Here it is, in as few words as possible. Focus on characters that need no escaping:

For cookies:


For urls


For cookies and urls ( intersection )


That's how you answer.

Note that for cookies, the = has been removed because it is usually used to set the cookie value.

For urls this the = was kept. The intersection is obviously without.

var chars = "abdefghijklmnqrstuvxyz"; chars += chars.toUpperCase() + "0123456789" + "!$&'()*+-.:@_~";

Turns out escaping still occuring and unexpected happening, especially in a Java cookie environment where the cookie is wrapped with double quotes if it encounters the last characters.

So to be safe, just use A-Za-z1-9. That's what I am going to do.

| improve this answer | |
  • Safari Cookies was my only problem browser – all others browsers worked fine. I had to UrlEncode and UrlDecode my cookie to deal with equal = signs and spaces. Like a Base64Encode in the Cookie. (Safari Only required this- other browsers worked fine with and without the encoded cookie.) – Sql Surfer Apr 25 '18 at 17:06
  • It is better if you list what sources leading to the your answer! – Loc Jun 7 '18 at 19:33
  • 1
    @Loc Over 3 hours of trial and inspecting. – mmm Jun 9 '18 at 1:28

Newer rfc6265 published in April 2011:


                   ; US-ASCII characters excluding CTLs,
                   ; whitespace DQUOTE, comma, semicolon,
                   ; and backslash

If you look to @bobince answer you see that newer restrictions are more strict.

| improve this answer | |


| improve this answer | |

There are 2 versions of cookies specifications
1. Version 0 cookies aka Netscape cookies,
2. Version 1 aka RFC 2965 cookies
version 1 is a lot more complicated you can check it here

| improve this answer | |

There is another interesting issue with IE and Edge. Cookies that have names with more than 1 period seem to be silently dropped. So This works:


while this will get dropped


| improve this answer | |
  • Would be great if you add the exact browser version in order for us to replicate, as browser behaviour is not consistent on cookies. – Gerald Jul 21 '18 at 1:30

that's simple:

A <cookie-name> can be any US-ASCII characters except control characters (CTLs), spaces, or tabs. It also must not contain a separator character like the following: ( ) < > @ , ; : \ " / [ ] ? = { }.

A <cookie-value> can optionally be set in double quotes and any US-ASCII characters excluding CTLs, whitespace, double quotes, comma, semicolon, and backslash are allowed. 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 though.

Link: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Directives

| improve this answer | |

One more consideration. I recently implemented a scheme in which some sensitive data posted to a PHP script needed to convert and return it as an encrypted cookie, that used all base64 values I thought were guaranteed 'safe". So I dutifully encrypted the data items using RC4, ran the output through base64_encode, and happily returned the cookie to the site. Testing seemed to go well until a base64 encoded string contained a "+" symbol. The string was written to the page cookie with no trouble. Using the browser diagnostics I could also verify the cookies was written unchanged. Then when a subsequent page called my PHP and obtained the cookie via the $_COOKIE array, I was stammered to find the string was now missing the "+" sign. Every occurrence of that character was replaced with an ASCII space.

Considering how many similar unresolved complaints I've read describing this scenario since then, often siting numerous references to using base64 to "safely" store arbitrary data in cookies, I thought I'd point out the problem and offer my admittedly kludgy solution.

After you've done whatever encryption you want to do on a piece of data, and then used base64_encode to make it "cookie-safe", run the output string through this...

// from browser to PHP. substitute troublesome chars with 
// other cookie safe chars, or vis-versa.  

function fix64($inp) {
    $out =$inp;
    for($i = 0; $i < strlen($inp); $i++) {
        $c = $inp[$i];
        switch ($c) {
            case '+':  $c = '*'; break; // definitly won't transfer!
            case '*':  $c = '+'; break;

            case '=':  $c = ':'; break; // = symbol seems like a bad idea
            case ':':  $c = '='; break;

            default: continue;
        $out[$i] = $c;
    return $out;

Here I'm simply substituting "+" (and I decided "=" as well) with other "cookie safe" characters, before returning the encoded value to the page, for use as a cookie. Note that the length of the string being processed doesn't change. When the same (or another page on the site) runs my PHP script again, I'll be able to recover this cookie without missing characters. I just have to remember to pass the cookie back through the same fix64() call I created, and from there I can decode it with the usual base64_decode(), followed by whatever other decryption in your scheme.

There may be some setting I could make in PHP that allows base64 strings used in cookies to be transferred back to to PHP without corruption. In the mean time this works. The "+" may be a "legal" cookie value, but if you have any desire to be able to transmit such a string back to PHP (in my case via the $_COOKIE array), I'm suggesting re-processing to remove offending characters, and restore them after recovery. There are plenty of other "cookie safe" characters to choose from.

| improve this answer | |

If you are using the variables later, you'll find that stuff like path actually will let accented characters through, but it won't actually match the browser path. For that you need to URIEncode them. So i.e. like this:

  const encodedPath = encodeURI(myPath);
  document.cookie = `use_pwa=true; domain=${location.host}; path=${encodedPath};`

So the "allowed" chars, might be more than what's in the spec. But you should stay within the spec, and use URI-encoded strings to be safe.

| improve this answer | |


| improve this answer | |

I ended up using

cookie_value = encodeURIComponent(my_string);


my_string = decodeURIComponent(cookie_value);

That seems to work for all kinds of characters. I had weird issues otherwise, even with characters that weren't semicolons or commas.

| improve this answer | |

Your Answer

