Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

@cursorial cursorial commented Sep 20, 2018

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

This comment has been minimized.

Copy link

@etgrieco 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

This comment has been minimized.

Copy link

@siberiadev siberiadev commented May 28, 2019

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

This comment has been minimized.

Copy link

@gentleShark gentleShark commented Jun 10, 2019

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

This comment has been minimized.

Copy link

@tail-call tail-call commented Jul 17, 2019

Succint

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

This comment has been minimized.

Copy link

@BlackLight BlackLight commented Jul 18, 2019

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

This comment has been minimized.

Copy link

@benqus 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

This comment has been minimized.

Copy link

@sz-cgt sz-cgt commented Oct 22, 2019

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

@tail-call

This comment has been minimized.

Copy link

@tail-call 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

This comment has been minimized.

Copy link

@kapouer 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

This comment has been minimized.

Copy link

@mohe2015 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

This comment has been minimized.

Copy link

@benqus 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

This comment has been minimized.

Copy link

@mohe2015 mohe2015 commented Aug 18, 2020

@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

This comment has been minimized.

Copy link

@jonnytest1 jonnytest1 commented Jan 14, 2021

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

@jaimegmx8

This comment has been minimized.

Copy link

@jaimegmx8 jaimegmx8 commented Mar 22, 2021

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

@angrymouse

This comment has been minimized.

Copy link

@angrymouse angrymouse commented May 22, 2021

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

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