Skip to content

Instantly share code, notes, and snippets.

@rendro
Last active February 28, 2024 03:05
Show Gist options
  • Star 29 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save rendro/525bbbf85e84fa9042c2 to your computer and use it in GitHub Desktop.
Save rendro/525bbbf85e84fa9042c2 to your computer and use it in GitHub Desktop.
Parse document.cookie into object
document.cookie.split(';').map(function(c) {
return c.trim().split('=').map(decodeURIComponent);
}).reduce(function(a, b) {
try {
a[b[0]] = JSON.parse(b[1]);
} catch (e) {
a[b[0]] = b[1];
}
return a;
}, {});
@cursorial
Copy link

This is good but it does mean iterating over the array twice because you're calling map and then reduce.

I refactored this so it will only iterate once with reduce.

document.cookie.split(';').reduce((cookieObject, cookieString) => {
  let splitCookie = cookieString.split('=').map((cookiePart) => { cookiePart.trim() })
  try {
    cookieObject[splitCookie[0]] = JSON.parse(splitCookie[1])
  } catch (error) {
    cookieObject[splitCookie[0]] = splitCookie[1]
  }
  return cookieObject
})

This way, we split the individual cookies by = and clean them up inside the reducer and save the extra map.

@etgrieco
Copy link

etgrieco commented Dec 13, 2018

A revision with ES6 syntax.

document.cookie
  .split(';')
  .reduce((res, c) => {
    const [key, val] = c.trim().split('=').map(decodeURIComponent)
    try {
      return Object.assign(res, { [key]: JSON.parse(val) })
    } catch (e) {
      return Object.assign(res, { [key]: val })
    }
  }, {});

and to maintain all number strings as strings (because JSON parses number strings as integers):

document.cookie
  .split(';')
  .reduce((res, c) => {
    const [key, val] = c.trim().split('=').map(decodeURIComponent)
    const allNumbers = str => /^\d+$/.test(str);
    try {
      return Object.assign(res, { [key]: allNumbers(val) ?  val : JSON.parse(val) })
    } catch (e) {
      return Object.assign(res, { [key]: val })
    }
  }, {});

@siberiadev
Copy link

Only this one works for me

let cookie = document.cookie.split(';').reduce((cookieObject, cookieString) => {
   		let splitCookie = cookieString.split('=')
   		try {
   		  cookieObject[splitCookie[0].trim()] = decodeURIComponent(splitCookie[1])
   		} catch (error) {
   			cookieObject[splitCookie[0].trim()] = splitCookie[1]
   		}
   		return cookieObject
   	}, [])

@gentleShark
Copy link

Only this one works for me

let cookie = document.cookie.split(';').reduce((cookieObject, cookieString) => {
   		let splitCookie = cookieString.split('=')
   		try {
   		  cookieObject[splitCookie[0].trim()] = decodeURIComponent(splitCookie[1])
   		} catch (error) {
   			cookieObject[splitCookie[0].trim()] = splitCookie[1]
   		}
   		return cookieObject
   	}, [])

you should be passing in an empty object to reduce instead of an array

@tail-call
Copy link

Succint

Object.fromEntries(document.cookie.split('; ').map(x => x.split('=')))

@blacklight
Copy link

It's 2019, and I'm surprised that there's no ES6 construct yet to get directly the cookies as a key->value map. And developers are still required to write their own boilerplate utility methods to parse the cookie string.

@benqus
Copy link

benqus commented Oct 17, 2019

Succint

Object.fromEntries(document.cookie.split('; ').map(x => x.split('=')))

That's a beauty one-liner but looking at the cookies at stackoverflow even the cookie values might contain = so based on your solution here's one that takes that into account as well - not a one-liner anymore though but I think my project might just survive with the 3 additional lines

Object.fromEntries(document.cookie.split('; ').map(c => {
    const [ key, ...v ] = c.split('=');
    return [ key, v.join('=') ];
}));

@sz-cgt
Copy link

sz-cgt commented Oct 22, 2019

One nit: split(/; */) is more robust than split('; ')

@tail-call
Copy link

tail-call commented Nov 7, 2019

Thanks @benqus, @sz-cgt, I improved it a little more

Object.fromEntries(document.cookie.split(/; */).map(c => {
    const [ key, ...v ] = c.split('=');
    return [ key, decodeURIComponent(v.join('=')) ];
}));

@kapouer
Copy link

kapouer commented Nov 15, 2019

@tail-call returns {"":""} when cookie is empty. It can crash if str is malformed. It splits uselessly.

 document.cookie.split(/; */).reduce((obj, str) => {
	if (str === "") return obj;
	const eq = str.indexOf('=');
	const key = eq > 0 ? str.slice(0, eq) : str;
	let val = eq > 0 ? str.slice(eq + 1) : null;
	if (val != null) try { val = decodeURIComponent(val); } catch(ex) { /* pass */ }
	obj[key] = val;
	return obj;
}, {});

@mohe2015
Copy link

mohe2015 commented Aug 13, 2020

Don't use, see comment below.

Object.fromEntries(document.cookie.split(/; */).map(cookie => cookie.split('=', 2)))

or with decodeURIComponent

Object.fromEntries(document.cookie.split(/; */).map(c => {
    const [ key, v ] = c.split('=', 2);
    return [ key, decodeURIComponent(v) ];
}));

@benqus
Copy link

benqus commented Aug 18, 2020

Object.fromEntries(document.cookie.split(/; */).map(cookie => cookie.split('=', 2)))

or with decodeURIComponent

Object.fromEntries(document.cookie.split(/; */).map(c => {
    const [ key, v ] = c.split('=', 2);
    return [ key, decodeURIComponent(v) ];
}));

That's not going to work because if you specify the limit for the String#split() then it'll ignore the remaining after the last split.

const array = "a=b=c".split("=", 2);
// array = ["a", "b"];

Cookie values may contain = as well

@mohe2015
Copy link

@benqus Thanks a lot, I should RTFM. I think I know programming languages where this actually keeps the remaining part but I'm not sure.

@jonnytest1
Copy link

.split(/=(.*)$/,2) thats what i did to keep the = at the end

@jaimegmx8
Copy link

Object.fromEntries(document.cookie.split('; ').map(x => x.split(/=(.*)$/,2).map(decodeURIComponent)))

@angrymouse
Copy link

angrymouse commented May 22, 2021

document.cookie.split("; ").reduce((a,c)=>{let [n,v]=c.split("=");return {...a,[n]:decodeURIComponent(v)};},{})

@12Me21
Copy link

12Me21 commented Aug 29, 2021

so these are neat, but does someone have one that's actually been properly tested?

@lourensdev
Copy link

@12Me21 I actually just ran into an issue using the reduce method. Seems that cookies with long values eventually get cut off, leading to obvious issues when you try do something with that value. I've instead opted to use the Object.fromEntries version with no issues so far

@12Me21
Copy link

12Me21 commented Nov 20, 2021

I've been using this:

function read_cookies() {
	let cookies = {}
	for (let item of document.cookie.split(";")) {
		let match = item.match(/^\s*([^]*?)="?([^]*?)"?\s*$/)
		if (match)
			cookies[match[1]] = decodeURIComponent(match[2])
	}
	return cookies
}

@norwd
Copy link

norwd commented Aug 24, 2022

Rewrite to work on older browsers / js versions:

Object.fromEntries(document.cookie.split(/; */).map(function(c) {
    var index = c.indexOf("=");     // Find the index of the first equal sign
    var key   = c.slice(0, index);  // Everything upto the index is the key
    var value = c.slice(index + 1); // Everything after the index is the value

    // Return the key and value
    return [ decodeURIComponent(key), decodeURIComponent(value) ];
}));

@nkitku
Copy link

nkitku commented Dec 1, 2022

https://stackoverflow.com/a/64472572/8784402

Object.fromEntries(document.cookie.split('; ').map(v=>v.split(/=(.*)/s).map(decodeURIComponent)))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment