Skip to content
Watch the complete Next.js 15 course on YouTube

Working with headers

This page explains how to work with HTTP headers in Next.js route handlers.

Understanding HTTP headers

HTTP headers represent the metadata associated with API requests and responses. This metadata can be classified into two main categories:

Request headers

Request headers are sent by the client (such as a web browser) to the server. They contain essential information about the request, which helps the server understand and process it correctly:

  • User-Agent: Identifies the browser and operating system to the server. Used for browser-specific content rendering and analytics.
  • Accept: Indicates the content types (text, video, image formats) that the client can process. Enables the server to deliver resources in a suitable format.
  • Authorization: Used by the client to authenticate itself to the server. Carries credentials allowing controlled access to resources.

Response headers

Response headers are sent from the server back to the client. They provide information about the server and the data being sent in the response:

  • Content-Type: Indicates the media type of the response. Tells the client what the data type of the returned content is (text/html, application/json, etc.).
  • Cache-Control: Directs how and for how long the response can be cached.
  • Access-Control-Allow-Origin: Specifies which origins can access the resource, part of CORS.

Reading request headers

Next.js provides two methods to read request headers in route handlers:

Method 1: Using the request parameter

app/api/profile/route.ts
import { type NextRequest } from "next/server";
export async function GET(request: NextRequest) {
const requestHeaders = new Headers(request.headers);
const authorization = requestHeaders.get("Authorization");
console.log(authorization); // "Bearer 12345"
// Process the request with the header information
return new Response("Profile data");
}

Method 2: Using the headers function

app/api/profile/route.ts
import { headers } from "next/headers";
export async function GET() {
const headersList = headers();
const authorization = headersList.get("Authorization");
console.log(authorization); // "Bearer 12345"
// Process the request with the header information
return new Response("Profile data");
}

Setting response headers

To set headers in your response, create a new Response object with custom headers:

app/api/profile/route.ts
export async function GET() {
return new Response("<h1>Profile API data</h1>", {
headers: {
"Content-Type": "text/html",
"Cache-Control": "no-cache, no-store, must-revalidate",
"X-Custom-Header": "custom-value",
},
});
}

Content type examples

Different content types affect how browsers interpret your response:

// Plain text response
return new Response("Hello World", {
headers: {
"Content-Type": "text/plain",
},
});
// HTML response
return new Response("<h1>Hello World</h1>", {
headers: {
"Content-Type": "text/html",
},
});
// JSON response
return Response.json({ message: "Hello World" });
// This automatically sets Content-Type to application/json

Good to know

  • Headers from the headers() function are read-only
  • To set headers, you must return a new Response with custom headers
  • Header names are case-insensitive
  • The Response.json() helper automatically sets the Content-Type to application/json
  • Use appropriate content types to ensure browsers interpret your response correctly