Files
next.js/docs/01-app/03-api-reference/04-functions/cookies.mdx
Delba de OliveiraGitHubVercel <vercel[bot]@users.noreply.github.com>Joseph
c2b4c0815c Unify caching story across the docs (#90149)
This PRs unifies the caching story across the docs, making Cache
Components the happy path, while still providing guidance to users in
the old model. However, instead of explaining the old model and its
caching layers, we've created a new guide focusing on what APIs to use
and when.

This follow-up PR aligns terminology across the docs:
https://github.com/vercel/next.js/pull/90589

## IA updates

Getting Started section: 

- Improves Getting Started progression:
- **Before:** CC → Fetching Data → Updating Data → Caching and
Revalidating (old and new model mixed)
- **After:** Fetching Data (Dynamic) → Mutating Data (Dynamic) → Caching
with CC (Prerendering) → Revalidating with CC.
- New: `caching.mdx` (CC-first)
   - Structure: 
      - Enabling Cache Components
      - Data vs UI-level caching
      - Working with request time APIs
      - Passing request values to cached functions
      - Working with non-deterministic operations
      - Working with synchronous operations
      - How rendering works (PPR and static shell story)
- New: `revalidating.mdx` (CC-first)
   - Explains how to use `cacheLife` and `cacheTag`

Guides Section: 

- New: `caching-and-revalidating.mdx` (Previous Model)
- For users who are not using CC, includes `fetch` options and route
segment config
- Moves route segment config options that don't apply to CC from API
reference to this guide (for easy archiving in the future).
- New: `migrating-to-cache-components.mdx` (WIP)
- Del: `caching.mdx` 😌 

## Terminology

We should remove caching layers from the docs. Users only needed to be
exposed to them when they were configured independently, but the new CC
APIs work across layers.

To make it easier to review this PR, I'm consolidating terminology and
fixing broken links in a new PR:
https://github.com/vercel/next.js/pull/90589

---------

Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: Joseph <[email protected]>
2026-03-03 13:14:24 +00:00

302 lines
12 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: cookies
description: API Reference for the cookies function.
---
`cookies` is an **async** function that allows you to read the HTTP incoming request cookies in [Server Components](/docs/app/getting-started/server-and-client-components), and read/write outgoing request cookies in [Server Functions](/docs/app/getting-started/mutating-data) or [Route Handlers](/docs/app/api-reference/file-conventions/route).
```tsx filename="app/page.tsx" switcher
import { cookies } from 'next/headers'
export default async function Page() {
const cookieStore = await cookies()
const theme = cookieStore.get('theme')
return '...'
}
```
```js filename="app/page.js" switcher
import { cookies } from 'next/headers'
export default async function Page() {
const cookieStore = await cookies()
const theme = cookieStore.get('theme')
return '...'
}
```
## Reference
### Methods
The following methods are available:
| Method | Return Type | Description |
| --------------------------- | ---------------- | ------------------------------------------------------------------------------- |
| `get('name')` | Object | Accepts a cookie name and returns an object with the name and value. |
| `getAll()` | Array of objects | Returns a list of all the cookies with a matching name. |
| `has('name')` | Boolean | Accepts a cookie name and returns a boolean based on if the cookie exists. |
| `set(name, value, options)` | - | Accepts a cookie name, value, and options and sets the outgoing request cookie. |
| `delete(name)` | - | Accepts a cookie name and deletes the cookie. |
| `toString()` | String | Returns a string representation of the cookies. |
### Options
When setting a cookie, the following properties from the `options` object are supported:
| Option | Type | Description |
| ------------- | -------------------------------------- | ---------------------------------------------------------------------------------- |
| `name` | String | Specifies the name of the cookie. |
| `value` | String | Specifies the value to be stored in the cookie. |
| `expires` | Date | Defines the exact date when the cookie will expire. |
| `maxAge` | Number | Sets the cookie’s lifespan in seconds. |
| `domain` | String | Specifies the domain where the cookie is available. |
| `path` | String, default: `'/'` | Limits the cookie's scope to a specific path within the domain. |
| `secure` | Boolean | Ensures the cookie is sent only over HTTPS connections for added security. |
| `httpOnly` | Boolean | Restricts the cookie to HTTP requests, preventing client-side access. |
| `sameSite` | Boolean, `'lax'`, `'strict'`, `'none'` | Controls the cookie's cross-site request behavior. |
| `priority` | String (`"low"`, `"medium"`, `"high"`) | Specifies the cookie's priority |
| `partitioned` | Boolean | Indicates whether the cookie is [partitioned](https://github.com/privacycg/CHIPS). |
The only option with a default value is `path`.
To learn more about these options, see the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies).
## Good to know
- `cookies` is an **asynchronous** function that returns a promise. You must use `async/await` or React's [`use`](https://react.dev/reference/react/use) function to access cookies.
- In version 14 and earlier, `cookies` was a synchronous function. To help with backwards compatibility, you can still access it synchronously in Next.js 15, but this behavior will be deprecated in the future.
- `cookies` is a [Request-time API](/docs/app/glossary#request-time-apis) whose returned values cannot be known ahead of time. Using it in a layout or page will opt a route into [dynamic rendering](/docs/app/glossary#dynamic-rendering).
- The `.delete` method can only be called:
- In a [Server Function](/docs/app/getting-started/mutating-data) or [Route Handler](/docs/app/api-reference/file-conventions/route).
- If it belongs to the same domain from which `.set` is called. For wildcard domains, the specific subdomain must be an exact match. Additionally, the code must be executed on the same protocol (HTTP or HTTPS) as the cookie you want to delete.
- HTTP does not allow setting cookies after streaming starts, so you must use `.set` in a [Server Function](/docs/app/getting-started/mutating-data) or [Route Handler](/docs/app/api-reference/file-conventions/route).
## Understanding Cookie Behavior in Server Components
When working with cookies in Server Components, it's important to understand that cookies are fundamentally a client-side storage mechanism:
- **Reading cookies** works in Server Components because you're accessing the cookie data that the client's browser sends to the server in the HTTP request headers.
- **Setting cookies** is not supported during Server Component rendering. To modify cookies, invoke a Server Function from the client or use a Route Handler.
The server can only send instructions (via `Set-Cookie` headers) to tell the browser to store cookies - the actual storage happens on the client side. This is why cookie operations that modify state (`.set`, `.delete`) must be performed in a Server Function or Route Handler where the response headers can be properly set.
## Understanding Cookie Behavior in Server Functions
After you set or delete a cookie in a Server Function, Next.js can return both the updated UI and new data in a single server roundtrip when the function is used as a [Server Action](/docs/app/getting-started/mutating-data#what-are-server-functions) (e.g., passed to a form's `action` prop). See [Caching and Revalidating](/docs/app/getting-started/caching).
The UI is not unmounted, but effects that depend on data coming from the server will re-run.
To refresh cached data too, call [`revalidatePath`](/docs/app/api-reference/functions/revalidatePath) or [`revalidateTag`](/docs/app/api-reference/functions/revalidateTag) inside the function.
## Examples
### Getting a cookie
You can use the `(await cookies()).get('name')` method to get a single cookie:
```tsx filename="app/page.tsx" switcher
import { cookies } from 'next/headers'
export default async function Page() {
const cookieStore = await cookies()
const theme = cookieStore.get('theme')
return '...'
}
```
```jsx filename="app/page.js" switcher
import { cookies } from 'next/headers'
export default async function Page() {
const cookieStore = await cookies()
const theme = cookieStore.get('theme')
return '...'
}
```
### Getting all cookies
You can use the `(await cookies()).getAll()` method to get all cookies with a matching name. If `name` is unspecified, it returns all the available cookies.
```tsx filename="app/page.tsx" switcher
import { cookies } from 'next/headers'
export default async function Page() {
const cookieStore = await cookies()
return cookieStore.getAll().map((cookie) => (
<div key={cookie.name}>
<p>Name: {cookie.name}</p>
<p>Value: {cookie.value}</p>
</div>
))
}
```
```jsx filename="app/page.js" switcher
import { cookies } from 'next/headers'
export default async function Page() {
const cookieStore = await cookies()
return cookieStore.getAll().map((cookie) => (
<div key={cookie.name}>
<p>Name: {cookie.name}</p>
<p>Value: {cookie.value}</p>
</div>
))
}
```
### Setting a cookie
You can use the `(await cookies()).set(name, value, options)` method in a [Server Function](/docs/app/getting-started/mutating-data) or [Route Handler](/docs/app/api-reference/file-conventions/route) to set a cookie. The [`options` object](#options) is optional.
```tsx filename="app/actions.ts" switcher
'use server'
import { cookies } from 'next/headers'
export async function create(data) {
const cookieStore = await cookies()
cookieStore.set('name', 'lee')
// or
cookieStore.set('name', 'lee', { secure: true })
// or
cookieStore.set({
name: 'name',
value: 'lee',
httpOnly: true,
path: '/',
})
}
```
```js filename="app/actions.js" switcher
'use server'
import { cookies } from 'next/headers'
export async function create(data) {
const cookieStore = await cookies()
cookieStore.set('name', 'lee')
// or
cookieStore.set('name', 'lee', { secure: true })
// or
cookieStore.set({
name: 'name',
value: 'lee',
httpOnly: true,
path: '/',
})
}
```
### Checking if a cookie exists
You can use the `(await cookies()).has(name)` method to check if a cookie exists:
```tsx filename="app/page.ts" switcher
import { cookies } from 'next/headers'
export default async function Page() {
const cookieStore = await cookies()
const hasCookie = cookieStore.has('theme')
return '...'
}
```
```jsx filename="app/page.js" switcher
import { cookies } from 'next/headers'
export default async function Page() {
const cookieStore = await cookies()
const hasCookie = cookieStore.has('theme')
return '...'
}
```
### Deleting cookies
There are three ways you can delete a cookie.
Using the `delete()` method:
```tsx filename="app/actions.ts" switcher
'use server'
import { cookies } from 'next/headers'
export async function deleteCookie(data) {
const cookieStore = await cookies()
cookieStore.delete('name')
}
```
```js filename="app/actions.js" switcher
'use server'
import { cookies } from 'next/headers'
export async function deleteCookie(data) {
const cookieStore = await cookies()
cookieStore.delete('name')
}
```
Setting a new cookie with the same name and an empty value:
```tsx filename="app/actions.ts" switcher
'use server'
import { cookies } from 'next/headers'
export async function deleteCookie(data) {
const cookieStore = await cookies()
cookieStore.set('name', '')
}
```
```js filename="app/actions.js" switcher
'use server'
import { cookies } from 'next/headers'
export async function deleteCookie(data) {
const cookieStore = await cookies()
cookieStore.set('name', '')
}
```
Setting the `maxAge` to 0 will immediately expire a cookie. `maxAge` accepts a value in seconds.
```tsx filename="app/actions.ts" switcher
'use server'
import { cookies } from 'next/headers'
export async function deleteCookie(data) {
const cookieStore = await cookies()
cookieStore.set('name', 'value', { maxAge: 0 })
}
```
```js filename="app/actions.js" switcher
'use server'
import { cookies } from 'next/headers'
export async function deleteCookie(data) {
const cookieStore = await cookies()
cookieStore.set('name', 'value', { maxAge: 0 })
}
```
## Version History
| Version | Changes |
| ------------ | ------------------------------------------------------------------------------------------------------ |
| `v15.0.0-RC` | `cookies` is now an async function. A [codemod](/docs/app/guides/upgrading/codemods#150) is available. |
| `v13.0.0` | `cookies` introduced. |