---
title: "Cookie Handling"
description: "Cookie handling in Hono is designed around web standards, providing a unified mechanism for parsing, serializing, and securing HTTP cookies across diverse serverless environments. By abstracting th..."
last_updated: "2026-07-02T09:13:47.293337+00:00"
canonical_url: "https://www.doc0.app/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/system-utilities/cookie-handling"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [src/utils/jwt/jwt.ts](https://github.com/blade47/hono/blob/main/src/utils/jwt/jwt.ts)
- [src/middleware/secure-headers/secure-headers.ts](https://github.com/blade47/hono/blob/main/src/middleware/secure-headers/secure-headers.ts)
- [src/adapter/aws-lambda/handler.ts](https://github.com/blade47/hono/blob/main/src/adapter/aws-lambda/handler.ts)
- [src/client/client.ts](https://github.com/blade47/hono/blob/main/src/client/client.ts)
- [src/context.ts](https://github.com/blade47/hono/blob/main/src/context.ts)
- [src/utils/cookie.ts](https://github.com/blade47/hono/blob/main/src/utils/cookie.ts)
- [src/middleware/jwt/jwt.ts](https://github.com/blade47/hono/blob/main/src/middleware/jwt/jwt.ts)
- [src/middleware/jwk/jwk.ts](https://github.com/blade47/hono/blob/main/src/middleware/jwk/jwk.ts)
- [src/middleware/bearer-auth/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/bearer-auth/index.ts)
- [src/middleware/csrf/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/csrf/index.ts)
- [src/middleware/language/language.ts](https://github.com/blade47/hono/blob/main/src/middleware/language/language.ts)
- [src/hono.ts](https://github.com/blade47/hono/blob/main/src/hono.ts)
- [src/helper/cookie/index.ts](https://github.com/blade47/hono/blob/main/src/helper/cookie/index.ts)
- [src/request.ts](https://github.com/blade47/hono/blob/main/src/request.ts)
- [src/utils/jwt/jws.ts](https://github.com/blade47/hono/blob/main/src/utils/jwt/jws.ts)
- [src/middleware/jwk/keys.test.json](https://github.com/blade47/hono/blob/main/src/middleware/jwk/keys.test.json)
- [src/adapter/lambda-edge/handler.ts](https://github.com/blade47/hono/blob/main/src/adapter/lambda-edge/handler.ts)
- [src/middleware/cors/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/cors/index.ts)
- [package.json](https://github.com/blade47/hono/blob/main/src/package.json)
- [src/client/fetch-result-please.ts](https://github.com/blade47/hono/blob/main/src/client/fetch-result-please.ts)
- [src/types.ts](https://github.com/blade47/hono/blob/main/src/types.ts)
</details>

Cookie handling in Hono is designed around web standards, providing a unified mechanism for parsing, serializing, and securing HTTP cookies across diverse serverless environments. By abstracting the complexities of the `Set-Cookie` header and cookie parsing, it allows developers to manage stateful interactions without worrying about low-level string manipulation or RFC-compliant parsing.

At its core, the subsystem balances ease of use with robust security requirements. It handles standard cookie parsing while offering specialized utilities for signed cookies, which ensure data integrity via HMAC-SHA256 signatures. This ensures that cookie values can be verified on the server side to detect tampering, a critical requirement for session and authentication management.

The architecture is built to be environment-agnostic. Because Hono aims to run on platforms ranging from Cloudflare Workers to AWS Lambda, the cookie utilities rely on the standard Web Crypto API (`crypto.subtle`) for signing operations and standard header management for persistence. This ensures that high-level abstractions remain performant and compliant with the security expectations of modern web applications.

## Parsing Mechanisms

The core parsing logic is implemented in `src/utils/cookie.ts`. The `parse` function handles incoming `Cookie` headers by splitting the string on semicolons and processing each key-value pair.

A key design choice here is the use of a "fast-path" for lookups. If a `name` is provided to `parse`, the implementation checks for its existence before fully iterating over the pairs, returning an empty object if the target key is absent.

```typescript
// Fast-path: return immediately if the demanded-key is not in the cookie string
if (name && cookie.indexOf(name) === -1) {
  return {}
}
```
Sources: [src/utils/cookie.ts:103-106](https://github.com/blade47/hono/blob/main/src/utils/cookie.ts#L103-L106)

Validation is strict. The code enforces name validity through a regular expression that checks for alphanumeric and specific special characters, and value validation via a regex that restricts characters to the ASCII range 32-126 (excluding forbidden ones like double quotes).

> [!TIP]
> The parser automatically unquotes values if they are enclosed in double quotes, providing seamless compatibility with varied client implementations.

Sources: [src/utils/cookie.ts:125-127](https://github.com/blade47/hono/blob/main/src/utils/cookie.ts#L125-L127)

## Serialization and Signing

Cookie serialization is handled by `_serialize`, which constructs the header string based on the provided `CookieOptions`. This includes attributes such as `Domain`, `Path`, `Max-Age`, and `Secure`.

To prevent tampering, `serializeSigned` (and `parseSigned`) facilitates HMAC-based signing. The mechanism:
1. Derives a `CryptoKey` using `crypto.subtle.importKey` with the HMAC SHA-256 algorithm.
2. Generates a base64 signature of the value.
3. Appends this signature to the value, separated by a dot (`value.signature`).

```typescript
const makeSignature = async (value: string, secret: string | BufferSource): Promise<string> => {
  const key = await getCryptoKey(secret)
  const signature = await crypto.subtle.sign(algorithm.name, key, new TextEncoder().encode(value))
  return btoa(String.fromCharCode(...new Uint8Array(signature)))
}
```
Sources: [src/utils/cookie.ts:44-49](https://github.com/blade47/hono/blob/main/src/utils/cookie.ts#L44-L49)

## Security and Prefix Enforcement

The system enforces RFC 6265bis recommendations for cookie prefixes, specifically `__Secure-` and `__Host-`. The `_serialize` function contains explicit guards to ensure these attributes are handled correctly.

| Prefix | Required Constraint |
| :--- | :--- |
| `__Secure-` | Must have the `Secure` attribute. |
| `__Host-` | Must have `Secure`, `Path='/'`, and no `Domain` attribute. |

If these invariants are not met, the code throws an explicit `Error`, preventing the creation of insecure cookies in sensitive contexts.

```typescript
if (name.startsWith('__Host-')) {
  if (!opt.secure) {
    throw new Error('__Host- Cookie must have Secure attributes')
  }
  // ... check path and domain
}
```
Sources: [src/utils/cookie.ts:179-192](https://github.com/blade47/hono/blob/main/src/utils/cookie.ts#L179-L192)

## Adapter-Level Integration

Different serverless adapters need different ways to set and get cookies. For example, AWS Lambda provides cookies in an event object for V2, while ALB might use `multiValueHeaders`. The `adapter/aws-lambda` implementation provides a `setCookies` mechanism that detects if `getSetCookie()` is available on the `Headers` object.

```typescript
this.setCookies(_event: E, res: Response, result: APIGatewayProxyResult) {
  if (res.headers.has('set-cookie')) {
    const cookies = res.headers.getSetCookie
      ? res.headers.getSetCookie()
      : Array.from(res.headers.entries())
          .filter(([k]) => k === 'set-cookie')
          .map(([, v]) => v)
    // ...
  }
}
```
Sources: [src/adapter/aws-lambda/handler.ts:388-401](https://github.com/blade47/hono/blob/main/src/adapter/aws-lambda/handler.ts#L388-L401)

This ensures that regardless of whether the platform supports the standard `getSetCookie()` API (common in modern runtimes), the handler can extract multiple cookies accurately.

## Helper API Surface

The `helper/cookie` module acts as the public-facing API for Hono applications. It provides high-level methods to interact with the `Context`.

```typescript
import { setCookie, getCookie } from 'hono/cookie'

app.get('/set', (c) => {
  setCookie(c, 'flavor', 'chocolate', { httpOnly: true, secure: true })
  return c.text('cookie set')
})
```
Sources: [src/helper/cookie/index.ts:99-102](https://github.com/blade47/hono/blob/main/src/helper/cookie/index.ts#L99-L102)

The helper layer handles the injection of the `Set-Cookie` header into the response, using `{ append: true }` to ensure multiple cookies can be set in a single response cycle.

## Design Trade-offs

| Design Choice | Benefit | Cost |
| :--- | :--- | :--- |
| **HMAC-SHA256 Signing** | Prevents client-side manipulation of cookie data. | Adds overhead to read/write operations (crypto latency). |
| **Strict Regex Enforcement** | High security by rejecting malformed cookie names/values. | May reject legacy cookies with unusual characters. |
| **Web Crypto Dependency** | Portability across modern serverless runtimes. | Requires async interfaces for `getSignedCookie`. |

Sources: [src/utils/cookie.ts:37-66](https://github.com/blade47/hono/blob/main/src/utils/cookie.ts#L37-L66), [src/utils/cookie.ts:70-77](https://github.com/blade47/hono/blob/main/src/utils/cookie.ts#L70-L77)

## Related

- [Context Execution](https://www.doc0.app/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/core-engine/context-execution)


## Sitemap

See the full [sitemap](https://www.doc0.app/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/llms.txt) for all pages in this wiki.
