NetSuite: Working With Cookies in Suitelets

Published on November 30, 2022.

One of the projects that I've been working on is a Web portal for a NetSuite client. The portal is built on the NetSuite platform as a Suitelet. It uses a customized and enhanced version of my SuiteFrame framework, and is being served up behind NGINX (using this technique that I shared back in January).

While developing the portal, I needed to add support for sessions. I'll write about how I'm managing sessions in a future post.

One of the things that I needed for session management was a way to work with cookies. In this post, I'll share some of the code that I wrote to do that.

Getting Cookies

When using a Suitelet, we have access to all of a request's headers, and can get to them via context.request.headers. Here's a sample of what the headers look like:

{
     "X-Akamai-SR-Hop": "1",
     "true-client-ip": "83.74.96.100",
     "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6.1 Safari/605.1.15",
     "x-forwarded-port": "443",
     "x-advpf-parse-category": "DEFAULT_ALLHTML",
     "Accept-Encoding": "gzip",
     "True-Client-IP": "83.74.96.100",
     "via": "1.1 v1-akamaitech.net(ghost) (AkamaiGHost), 1.1 akamai.net(ghost) (AkamaiGHost)",
     "x-forwarded-host": "9999999-sb3.extforms.netsuite.com:443, 9999999-sb3.extforms.netsuite.com",
     "host": "9999999-sb3.extforms.netsuite.com",
     "X-Advpf-Parse-Category": "DEFAULT_ALLHTML",
     "ns-client-ip": "83.74.96.100",
     "connection": "keep-alive",
     "cache-control": "no-cache, max-age=0",
     "X-Real-IP": "55.140.23.28",
     "Cookie": "sessionID=20170094-2961ae54-de92-49ac-a0a8-93f13786fede; NS_ROUTING_VERSION=LAGGING; c7tXy98SOdcsRmaJORP2xg=AAABhHfmy1MPCnHzorzdLrEhYIuHIuNVNakHqWKIjIhEl5W8hlAI5A",
     "NS-Client-IP": "83.74.96.100",
     "Akamai-Origin-Hop": "2",
     "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
     "cookie": "sessionID=20170094-2961ae54-de92-49ac-a0a8-93f13786fede; NS_ROUTING_VERSION=LAGGING; c7tXy98SOdcsRmaJORP2xg=AAABhHfmy1MPCnHzorzdLrEhYIuHIuNVNakHqWKIjIhEl5W8hlAI5A",
     "x-forwarded-proto": "https",
     "accept-language": "en-US,en;q=0.9",
     "X-Forwarded-Proto": "https",
     "X-Forwarded-Host": "9999999-sb3.extforms.netsuite.com:443, 9999999-sb3.extforms.netsuite.com",
     "Akamai-GRN": "0.4f6adc17.1669841763.d8873b13, 0.378cd017.1669841763.4e34b9ba",
     "Connection": "keep-alive",
     "Host": "9999999-sb3.extforms.netsuite.com",
     "Pragma": "no-cache",
     "x-forwarded-for": "83.74.96.100, 23.220.106.79, 55.140.23.28, 10.136.0.13",
     "X-Forwarded-Port": "443",
     "akamai-origin-hop": "2",
     "pragma": "no-cache",
     "Via": "1.1 v1-akamaitech.net(ghost) (AkamaiGHost), 1.1 akamai.net(ghost) (AkamaiGHost)",
     "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
     "x-real-ip": "55.140.23.28",
     "x-akamai-sr-hop": "1",
     "X-Akamai-CONFIG-LOG-DETAIL": "true",
     "x-akamai-config-log-detail": "true",
     "x-forwarded-server": "forms.na7.netsuite.com",
     "Cache-Control": "no-cache, max-age=0",
     "X-Forwarded-For": "83.74.96.100, 23.220.106.79, 55.140.23.28, 10.136.0.13",
     "Accept-Language": "en-US,en;q=0.9",
     "X-Forwarded-Server": "forms.na7.netsuite.com",
     "accept-encoding": "gzip",
     "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.2.35 (KHTML, like Gecko) Version/15.16.1 Safari/605.2.35",
     "akamai-grn": "0.4f6adc17.1669841763.d8873b13, 0.327cd017.1669841763.4e34b9ba"
}

Each header is listed twice, once with header name in lower case, and a second time in intercaps. I usually refer to the lower case versions, but I don't think it matters all that much.

Cookies are available via the "cookie" header. It looks like this:

"cookie": "sessionID=20170094-2961ae54-de92-49ac-a0a8-93f13786fede; NS_ROUTING_VERSION=LAGGING; c7tXy98SOdcsRmaJORP2xg=AAABhHfmy1MPCnHzorzdLrEhYIuHIuNVNakHqWKIjIhEl5W8hlAI5A"

So we can reference it using context.request.headers['cookie']. That's easy enough. But that returns the entire cookie string value. To parse it, I wrote this function, which takes the script context, gets the cookie header, parses it, and returns it as an object.

function cookiesGet( context ) {
			
	var cookies = {}
	
	var cookiesOriginal = context.request.headers['cookie'];
	
	if ( cookiesOriginal == null ) {
		return cookies;
	}			
	
	cookiesOriginal = cookiesOriginal.split("; ");	    							
	
	for ( var i = 0; i < cookiesOriginal.length; i++ ){	    		
	
		var thisCookie = cookiesOriginal[i];
		
		thisCookie = thisCookie.split("=");	 
		
		cookies[thisCookie[0]] = thisCookie[1];
		
	}
	
	return cookies;
	
}	

The result will look something like this:

{
     "sessionID": "20170094-2961ae54-de92-49ac-a0a8-93f13786fede",
     "NS_ROUTING_VERSION": "LAGGING",
     "c7tXy98SOdcsRmaJORP2xg": "AAABhHfmy1MPCnHzorzdLrEhYIuHIuNVNakHqWKIjIhEl5W8hlAI5A"
}

Setting Cookies

To set cookies in a Suitelet, we can use the context.response.setHeader method. For example, to drop a cookie with name-value pair "a=1" you would use something like this:

context.response.setHeader( { name: 'Set-Cookie', value: 'a=1; path=/' } );

Dropping multiple name-value pairs can be tricky. For example, to set a second name-value pair ("b=2") you might try this...

context.response.setHeader( { name: 'Set-Cookie', value: 'a=1; b=2; path=/' } );

But the resulting cookie will only include the first name-value pair, and ignore the second.

Calling the setHeader method twice, like this...

context.response.setHeader( { name: 'Set-Cookie', value: 'a=1; path=/' } );
context.response.setHeader( { name: 'Set-Cookie', value: 'b=2; path=/' } );

... will result in a cookie that includes only the second name-value pair.

One method that I've found to solve this issue is to put the values in an object, JSON-encode the object, and then URL-encode the JSON string. For example...

let values = {a: 1, b: 2}
values = JSON.stringify(values);
values = encodeURIComponent(values);
context.response.setHeader( { name: 'Set-Cookie', value: `values=${values}; path=/` } );

You would then read the cookie, and decode it. For example...

let cookies = cookiesGet( context );
let values = cookies.values;
values = decodeURIComponent(values);
values = JSON.parse( values );

Wrapping Up

I hope you find this short post to be helpful.

Happy SuiteScripting!

About Me

Hello, I’m Tim Dietrich. I design and build custom software for businesses running on NetSuite — from mobile apps and Web portals to Web APIs and integrations.

I’ve created several widely used open-source solutions for the NetSuite community, including the SuiteQL Query Tool and SuiteAPI, which help developers and businesses get more out of their systems.

I’m also the founder of SuiteStep, a NetSuite development studio focused on pushing the boundaries of what’s possible on the platform. Through SuiteStep, I deliver custom software and AI-driven solutions that make NetSuite more powerful, accessible, and future-ready.

Copyright © 2025 Tim Dietrich.