Library / SDK
expressjs/cookie-parser avatar
expressjs/cookie-parser

cookie-parser: reading the Cookie header and verifying signed values in Express

Parse HTTP request cookies

2,030 stars236 forksJavaScriptMIT

At a glance

What is it?
cookie-parser is a focused Express middleware that parses the Cookie header into req.cookies and, when a secret is configured, verifies signed cookies into req.signedCookies. Its narrow scope makes the gaps easy to spot before you depend on it.
Who is it for?
cookie-parser is the right choice for any Express application that needs to read cookies on the incoming request, and its HMAC signing through cookie-signature 1.0.6 is sufficient for protecting session identifiers when a full session store is not available. It is the wrong choice when the cookie value must remain unreadable in transit, because HMAC is an integrity mechanism and not encryption.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 131 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What req.cookies and req.signedCookies hold after the header is parsed

cookie-parser's job is reading cookies, not setting them. When a request arrives, Express leaves the Cookie header as a raw string. Mounting cookie-parser with app.use transforms that string into two objects on the request: req.cookies, which holds every cookie that arrived without a signed prefix, and req.signedCookies, which holds cookies whose HMAC signature matched the secret you configured.

That split is a deliberate design choice. A session token you want to protect from client-side tampering ends up in req.signedCookies if the signature is valid. Anything that arrived without the s: prefix ends up in req.cookies. Route code checking req.signedCookies.sessionId knows it is reading a value whose integrity was verified. Code checking req.cookies.theme is reading an unverified value, and that distinction is visible without inspecting the value string.

Two optional arguments configure the middleware behavior. First is secret, a string or an array of strings used as the HMAC key for both signing and verification. Second is options, forwarded unchanged to the underlying cookie package. Both can be omitted when signed cookies are not needed and no custom decoding is required.

Installing version 1.4.7 and the first route that reads cookies

cookie-parser is published on npm. Install it with:

sh
$ npm install cookie-parser

Package.json records version 1.4.7 as the current release, published on 2024-10-08. The engines field requires Node.js 0.8.0 or newer. Two runtime dependencies are pinned: cookie at 0.7.2, which handles the actual header parsing, and cookie-signature at 1.0.6, which handles HMAC verification.

A minimal working example from the README listens on port 8080:

js
var express = require('express')
var cookieParser = require('cookie-parser')

var app = express()
app.use(cookieParser())

app.get('/', function (req, res) {
  // Cookies that have not been signed
  console.log('Cookies: ', req.cookies)

  // Cookies that have been signed
  console.log('Signed Cookies: ', req.signedCookies)
})

app.listen(8080)

With no secret passed, req.signedCookies prints empty. A curl command for testing the running server also appears in the README:

sh
curl http://127.0.0.1:8080 --cookie "Cho=Kim;Greet=Hello"

That sends two cookies, Cho with value Kim and Greet with value Hello, to the route handler. Both appear in req.cookies because neither carries the s: prefix.

The s: prefix convention and what a tampered cookie returns

Signed cookies carry a specific value format. The cookie value must begin with the literal string s:, followed by the payload and an HMAC signature. cookie-parser reads that prefix, separates the payload from the signature, and verifies the signature against the configured secret.

A valid signature causes the verified value to appear in req.signedCookies under the cookie's name, without the prefix. An invalid or modified signature does not cause an exception. The README states directly that signed cookies failing validation receive the value false in req.signedCookies rather than the tampered value. A client that strips the signature from a signed cookie and sends the bare value does not match the s: prefix, so the cookie goes to req.cookies as a plain string instead.

That false-not-exception behavior is worth planning around. If a route checks req.signedCookies.sessionId, a valid session is a non-false string, a tampered session is false, and a missing or unsigned session is undefined. All three are distinct states.

When secret is an array rather than a string, cookie-parser tries each element in sequence and accepts the first that produces a valid signature. That lets an application rotate its signing key without immediately invalidating all existing cookies that were signed with an older secret.

JSON cookies, the j: prefix, and what happens when JSON.parse fails

A second special prefix, j:, marks a cookie whose value is a JSON-encoded string that cookie-parser will parse before it reaches the route handler. When it encounters this prefix, cookie-parser removes it and passes the remainder to JSON.parse. A successful parse replaces the raw string with the parsed JavaScript value in req.cookies. The README states that if parsing fails, the original value remains, so a malformed j:-prefixed cookie silently comes through as its raw string rather than throwing.

The j: convention is not a standard HTTP mechanism. No browser adds that prefix automatically. It appears when the application sets cookies using a library that serializes objects, and the same application reads them back with cookie-parser. A cookie that arrived from a third-party client without that prefix is handled as plain text regardless of its content.

The static cookieParser.JSONCookie function handles a single string. It returns the parsed object if the value is a valid JSON cookie, and returns the original string otherwise. cookieParser.JSONCookies handles an entire object by calling JSONCookie on every value, modifying the object in place, and returning the same object reference. Code that stores the return value of JSONCookies is storing a reference to the original object, not a separate copy.

The decode option and what it controls inside the cookie package

Options passed to cookieParser go directly to the parse function of the cookie 0.7.2 package. One option is documented by name: decode, a function that replaces the default percent-decoding applied to each cookie value before it is stored in req.cookies.

By default, percent-decoding handles URL-encoded characters in cookie values. Supplying a custom function takes over that responsibility entirely. There is no way to apply a custom decode function to only some cookies while leaving others at the default: every value that arrives in the Cookie header passes through whichever decode function is active.

Because the options object goes to cookie.parse rather than being processed by cookie-parser itself, options other than decode that cookie 0.7.2 accepts are also passed through. Only decode is named in the README; other options accepted by cookie 0.7.2 require reading that package's own documentation. Pinning to exactly 0.7.2 in package.json, rather than a version range, means the available option set is fixed until that dependency is explicitly updated.

signedCookies removes keys from the input object; JSONCookies returns the same reference

cookieParser.signedCookies and cookieParser.JSONCookies, the two collection-level static methods, handle mutation differently in a way a quick read of their API descriptions can miss.

cookieParser.signedCookies takes a cookies object and, for each valid signed cookie it finds, deletes that key from the input object and adds the verified value to a new object it creates and returns. Deletion mutates the input object. What returns is a new object containing only the verified signed cookies.

cookieParser.JSONCookies also mutates its input, but the README explicitly states that it returns the same object that was passed in. It overwrites parsed JSON values in place. Return value and input are the same object reference.

Both methods are used internally by the middleware to build req.cookies and req.signedCookies from the raw parsed header. That difference matters when application code calls either method after middleware has already processed the request: signedCookies will again delete keys from whichever object it receives, and JSONCookies will overwrite values in place, which affects any other code holding a reference to the same object.

Reading cookies is the full scope; writing, encryption, and response attributes are elsewhere

cookie-parser reads the incoming Cookie header. Setting cookies on a response is done through Express's own res.cookie method, which writes Set-Cookie headers. cookie-parser has no involvement in that direction and exposes no API for it.

HMAC signing through cookie-signature 1.0.6 provides integrity, not confidentiality. Anyone who can observe the Cookie header, whether through a network interception or a logging system, can read the value. Verification lets the server confirm the value has not been modified since it was set. Encryption of cookie values is outside the scope of this package, and cookie-signature 1.0.6 does not offer it.

Attributes that control cookie behavior in the browser, such as HttpOnly, SameSite, Secure and Max-Age, appear in the Set-Cookie header when the cookie is created. cookie-parser reads the Cookie header on incoming requests and has no access to those attributes. Whether a cookie was originally set as Secure or HttpOnly is not visible in the Cookie header, and cookie-parser makes no attempt to infer it. Those attributes need to be verified at the point where res.cookie is called.

The 0.8.0 Node.js floor, the three published files, and what the test suite covers

Node.js 0.8.0 or newer is required, as stated in the engines field. That floor is low relative to the current Node.js LTS cadence, and any modern version satisfies it. No supported versions table appears in the README, so the requirement does not communicate what the maintainers actually test against.

Package.json's files array names three items that ship with the package: index.js, HISTORY.md, and the copyright file. TypeScript declaration files are not among them. Funding comes through Open Collective under the Express organization, as stated in the funding field of package.json. The last push to the repository was on 2026-06-03.

A test directory lives at the repository root, and mocha drives the suite:

sh
mocha --reporter spec --bail --check-leaks test/

Package.json also defines a coverage variant under test-cov that writes an HTML report via nyc, and a test-ci variant that writes lcov output. Neither requires additional configuration beyond installing dev dependencies.

Editorial conclusion

cookie-parser is the right choice for any Express application that needs to read cookies on the incoming request, and its HMAC signing through cookie-signature 1.0.6 is sufficient for protecting session identifiers when a full session store is not available. It is the wrong choice when the cookie value must remain unreadable in transit, because HMAC is an integrity mechanism and not encryption. Before deploying, confirm that your code distinguishes false in req.signedCookies from undefined, because a tampered signed cookie returns false rather than throwing, and treating the two the same is a security gap.

Frequently asked questions

What does cookie-parser do in an Express application?

It reads the Cookie header on each incoming request and populates req.cookies with the parsed name-value pairs. When a secret is provided at setup, it also verifies signed cookies and places the verified values in req.signedCookies.

How do signed cookies work in cookie-parser?

A signed cookie carries the prefix s: in its value, and cookie-parser uses HMAC with the secret you supplied to verify it. A cookie that fails validation is placed in req.signedCookies with the value false rather than raising an exception.

Does cookie-parser encrypt cookie values?

No. It uses HMAC via the cookie-signature 1.0.6 package to verify that a value has not been tampered with, but the value itself remains readable in the Cookie header. Encryption is outside the scope of this package.

What is the difference between req.cookies and req.signedCookies?

req.cookies holds cookies that arrived without a signature or whose values do not start with s:. req.signedCookies holds cookies that carried a valid s: prefix and passed HMAC verification against the configured secret.

How do I pass a custom decode function to cookie-parser?

Pass an options object as the second argument to cookieParser, with a decode property set to your function. The README states that options is forwarded directly to the parse function of the underlying cookie 0.7.2 package.

Official sources

  1. expressjs/cookie-parser on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/expressjs-cookie-parser.svg)](https://hysenlabs.com/projects/expressjs-cookie-parser)