Cookies & Headers
Leia e defina cookies e headers no servidor com as APIs cookies() e headers() de next/headers.
Busque em todas as páginas da documentação
Leia e defina cookies e headers no servidor com as APIs cookies() e headers() de next/headers.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Cartão de receita de referência rápida - pronto para copiar e colar.
import { cookies, headers } from "next/headers";
// Lendo cookies (assíncrono no Next.js 15+)
export default async function Page() {
const cookieStore = await cookies();
const theme = cookieStore.get("theme")?.value ?? "light";
const token = cookieStore.get("auth-token")?.value;
// Lendo headers
const headersList = await headers();
const userAgent = headersList.get("user-agent") ?? "";
const ip = headersList.get("x-forwarded-for") ?? "unknown";
return <div>Theme: {theme}</div>;
}
// Definindo cookies em uma Server Action
"use server";
import { cookies } from "next/headers";
export async function setTheme(theme: string) {
const cookieStore = await cookies();
cookieStore.set("theme", theme, {
httpOnly: true,
secure: true,
sameSite: "lax",
maxAge: 60 * 60 * 24 * 365, // 1 ano
});
}Quando usar isso: Você precisa ler tokens de autenticação, preferências de idioma, flags de recursos ou quaisquer outros dados por requisição de cookies ou headers.
// app/layout.tsx (Server Component)
import { cookies, headers } from "next/headers";
export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const cookieStore = await cookies();
const theme = cookieStore.get("theme")?.value ?? "system";
const locale = cookieStore.get("locale")?.value ?? "en";
const headersList = await headers();
const acceptLanguage = headersList.get("accept-language");
return (
<html lang={locale} data-theme={theme}>
<body>{children}</body>
</html>
);
}// app/actions/preferences.ts
"use server";
import { cookies } from "next/headers";
import { revalidatePath } from "next/cache";
export async function setTheme(formData: FormData) {
const theme = formData.get("theme") as string;
if (!["light", "dark", "system"].includes(theme)) {
return { error: "Invalid theme" };
}
const cookieStore = await cookies();
cookieStore.set("theme", theme, {
httpOnly: false, // permite que o JS do cliente leia para atualização imediata da UI
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
path: "/",
maxAge: 60 * 60 * 24 * 365,
});
revalidatePath("/", "layout");
}
export async function setLocale(locale: string) {
const cookieStore = await cookies();
cookieStore.set("locale", locale, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
path: "/",
maxAge: 60 * 60 * 24 * 365,
});
revalidatePath("/", "layout");
}// app/components/theme-switcher.tsx
"use client";
import { useTransition } from "react";
import { setTheme } from "@/app/actions/preferences";
export function ThemeSwitcher({ currentTheme }: { currentTheme: string }) {
const [isPending, startTransition] = useTransition();
const themes = ["light", "dark", "system"] as const;
return (
<div className="flex gap-2">
{themes.map((theme) => (
<button
key={theme}
onClick={() =>
startTransition(async () => {
const fd = new FormData();
fd.set("theme", theme);
await setTheme(fd);
})
}
className={`px-3 py-1 rounded border ${
currentTheme === theme
? "bg-blue-600 text-white"
: "bg-white text-gray-700"
} ${isPending ? "opacity-50" : ""}`}
disabled={isPending}
>
{theme}
</button>
))}
</div>
);
}// middleware.ts -- lendo e definindo cookies/headers no Middleware
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(request: NextRequest) {
// Lendo um cookie
const locale = request.cookies.get("locale")?.value ?? "en";
// Lendo um header
const country = request.headers.get("x-vercel-ip-country") ?? "US";
// Definindo um header para uso posterior
const response = NextResponse.next();
response.headers.set("x-locale", locale);
response.headers.set("x-country", country);
// Definindo um cookie
if (!request.cookies.has("visitor-id")) {
response.cookies.set("visitor-id", crypto.randomUUID(), {
httpOnly: true,
secure: true,
sameSite: "lax",
maxAge: 60 * 60 * 24 * 365,
});
}
return response;
}O que isso demonstra:
cookies() e headers() são funções assíncronas no Next.js 15+ que retornam a loja de cookies e o mapa de headers para a requisição atual.cookies() retorna um objeto ReadonlyRequestCookies quando lido em Server Components. Em Server Actions e Route Handlers, retorna uma loja gravável que suporta .set() e .delete().headers() retorna um objeto Headers somente leitura. Você não pode definir headers de resposta a partir de um Server Component -- use Middleware ou Route Handlers para isso.Set-Cookie. O navegador os aplica imediatamente.Excluindo um cookie:
"use server";
import { cookies } from "next/headers";
export async function logout() {
const cookieStore = await cookies();
cookieStore.delete("auth-token");
cookieStore.delete("session");
}Lendo todos os cookies:
const cookieStore = await cookies();
const allCookies = cookieStore.getAll();
// [{ name: "theme", value: "dark" }, { name: "locale", value: "en" }]Verificando se um cookie existe:
const cookieStore = await cookies();
const hasAuth = cookieStore.has("auth-token");Definindo headers de resposta em um Route Handler:
// app/api/data/route.ts
import { NextResponse } from "next/server";
export async function GET() {
const data = await fetchData();
return NextResponse.json(data, {
headers: {
"Cache-Control": "public, max-age=3600",
"X-Custom-Header": "my-value",
},
});
}import { cookies, headers } from "next/headers";
// cookies() retorna Promise<ReadonlyRequestCookies> em Server Components
// e Promise<RequestCookies> em Server Actions (gravável)
const cookieStore = await cookies();
const value: string | undefined = cookieStore.get("key")?.value;
// headers() retorna Promise<ReadonlyHeaders>
const headersList = await headers();
const value: string | null = headersList.get("x-custom");
// Tipo de opções de cookie
type CookieOptions = {
name: string;
value: string;
domain?: string;
path?: string;
maxAge?: number;
expires?: Date;
httpOnly?: boolean;
secure?: boolean;
sameSite?: "strict" | "lax" | "none";
};cookies() e headers() tornam a rota dinâmica -- Qualquer Server Component ou layout que chame essas funções não pode ser gerado estaticamente. Correção: Se você precisa do valor do cookie apenas para interatividade, leia-o no cliente com document.cookie ou uma biblioteca como js-cookie em vez disso.
Não é possível definir cookies em Server Components -- A loja de cookies é somente leitura fora de Server Actions e Route Handlers. Correção: Use uma Server Action para definir cookies, ou defina-os no Middleware.
cookies() é assíncrono no Next.js 15+ -- Chamar cookies() sem await retorna uma Promise, não a loja de cookies. Correção: Sempre use const cookieStore = await cookies().
Cookies do Middleware vs Cookies de Server Components -- Cookies definidos no Middleware via response.cookies.set() estão disponíveis para Server Components downstream via cookies() na mesma requisição. No entanto, cookies definidos em Server Actions só estão disponíveis na próxima requisição. Correção: Entenda o ciclo de vida da requisição; use Middleware para injeção de cookies por requisição.
sameSite: "none" requer secure: true -- Navegadores rejeitam cookies SameSite=None sem o flag Secure. Correção: Sempre combine sameSite: "none" com secure: true.
Limites de tamanho de cookie -- Navegadores limitam cookies individuais a aproximadamente 4 KB e cookies totais por domínio a cerca de 80. Correção: Armazene dados mínimos em cookies; use um ID de sessão apontando para armazenamento no lado do servidor para cargas úteis grandes.
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Cookies do Middleware | Você precisa ler ou definir cookies antes do processamento da rota | Você só precisa de cookies dentro de uma Server Action |
document.cookie (cliente) | Você precisa ler um cookie não-httpOnly para atualizações imediatas da UI | Você precisa de acesso no lado do servidor ou cookies httpOnly |
Biblioteca js-cookie | Você quer uma API mais amigável para gerenciamento de cookies no lado do cliente | Você está trabalhando em Server Components |
| Armazenamento de sessão (ex: iron-session) | Você precisa de dados de sessão criptografados e à prova de adulteração | Preferências simples de chave-valor são suficientes |
searchParams | Os dados devem ser visíveis na URL e compartilháveis | Os dados são sensíveis ou específicos do usuário |
document.cookie em vez dissocookies() sem await lhe dá um objeto Promise, não a loja de cookiesconst cookieStore = await cookies()Set-Cookie e só estão disponíveis na próxima requisição"use server";
import { cookies } from "next/headers";
export async function logout() {
const cookieStore = await cookies();
cookieStore.delete("auth-token");
cookieStore.delete("session");
}SameSite=None requer que o flag Secure seja definidosameSite: "none" com secure: trueNextResponse.json(data, { headers: {...} })response.headers.set("key", "value")// Server Component: ReadonlyRequestCookies (somente leitura)
const cookieStore = await cookies();
cookieStore.get("key"); // OK
// cookieStore.set(...) // Erro
// Server Action: RequestCookies (gravável)
const cookieStore = await cookies();
cookieStore.set("key", "value", { httpOnly: true }); // OKtype CookieOptions = {
name: string;
value: string;
domain?: string;
path?: string;
maxAge?: number;
expires?: Date;
httpOnly?: boolean;
secure?: boolean;
sameSite?: "strict" | "lax" | "none";
};const cookieStore = await cookies();
const allCookies = cookieStore.getAll();
// [{ name: "theme", value: "dark" }, { name: "locale", value: "en" }]httpOnly: false permite que o JavaScript do cliente leia o cookie para atualizações imediatas da UI (por exemplo, tema)httpOnly: true impede o acesso do JavaScript, protegendo tokens sensíveis contra ataques XSShttpOnly: true para cookies de autenticação e sessãoRevisado por Chris St. John·Última atualização: 19 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥