W3docs

PHP header() Function: Everything You Need to Know

As a PHP developer, you may need to manipulate HTTP headers in your web application. The header() function is a powerful tool that allows you to set HTTP

Every HTTP response a web server sends has two parts: a set of headers (metadata such as the content type, caching rules, and status code) followed by the response body (the HTML, JSON, image, or file the browser receives). PHP's header() function lets you write those headers from your script — so you can redirect users, serve downloads, set the content type, control caching, and send custom status codes.

This guide covers the syntax and parameters of header(), the one rule that trips up almost everyone (the "headers already sent" error), and the most common real-world recipes.

What is the header() Function?

header() is a built-in PHP function that sends a raw HTTP header to the client. A header is a single line such as Content-Type: text/html or Location: /login that the browser reads before the page body. Because the headers come first in the response, header() only works while PHP is still building that header section — see the "headers already sent" rule below.

Syntax and Parameters

header(string $header, bool $replace = true, int $response_code = 0): void
ParameterTypeDescription
$headerstringThe header line to send, e.g. "Content-Type: application/json".
$replaceboolWhether this call replaces a previous header of the same name. When false, multiple headers of the same name are sent. Defaults to true.
$response_codeintForces the HTTP status code of the response. 0 (the default) means "leave the status unchanged".

The function returns nothing (void). It does not tell you whether the header was accepted — if output was already sent, it raises a warning instead.

Setting a header

The simplest use is declaring what kind of content the response contains. This is essential when your script returns JSON, XML, plain text, or a file instead of HTML:

<?php

header("Content-Type: application/json");

echo json_encode(["status" => "ok", "id" => 42]);

The Content-Type header tells the browser to treat the body as JSON, so it parses {"status":"ok","id":42} as data rather than rendering it as a web page.

The "headers already sent" rule

This is the single most important thing to know about header(): it must be called before any output leaves your script. Output includes HTML, echo/print, var_dump(), and even a stray space or blank line before the opening <?php tag. Once one byte of the body has been sent, the header section is closed and PHP raises:

Warning: Cannot modify header information - headers already sent

You have two ways to avoid it:

<?php

// 1. Check first — useful when a header is optional
if (!headers_sent()) {
    header("X-Powered-By: MyApp");
}

// 2. Buffer output so nothing is flushed until you choose to
ob_start();                 // capture everything that gets echoed
echo "page content...";
header("X-Cache: MISS");    // still works — body is held in the buffer
ob_end_flush();             // now send headers + buffered body together

A common cause is an editor saving the file with a UTF-8 BOM or a newline after ?>. Omitting the closing ?> tag entirely in pure-PHP files is the recommended way to avoid that.

Common use cases

Redirecting to another URL

Send a Location header, then stop the script so no further code runs:

<?php

header("Location: https://example.com/login");
exit;   // always exit after a redirect

By default this is a 302 Found (temporary) redirect. For a permanent move, pass 301 as the status code so search engines update their index:

<?php

// 301 Moved Permanently
header("Location: https://example.com/new-page", true, 301);
exit;

Sending a custom status code

You can set a status without redirecting — for an API returning "not found", for example:

<?php

header("HTTP/1.1 404 Not Found");
// or, more portably:
header("Status: 404 Not Found", true, 404);

echo "Resource not found";

For status codes specifically, the dedicated http_response_code() function is clearer and easier to read.

Forcing a file download

Combine Content-Type with Content-Disposition: attachment to make the browser save the file instead of displaying it:

<?php

$file = "report.pdf";

header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Length: " . filesize($file));

readfile($file);   // stream the file to the client
exit;

See readfile() for streaming the file contents to the output.

Controlling browser caching

Headers let you tell the browser whether (and for how long) it may reuse a response:

<?php

// Tell the browser never to cache this response
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Expires: 0");

Sending multiple headers of the same name

Most headers replace any previous one with the same name. Set the second argument to false when you genuinely need more than one (rare, but valid for some headers):

<?php

header("X-Sample: first");
header("X-Sample: second", false);   // both X-Sample headers are sent

header() writes one header at a time, but PHP has higher-level helpers for the most common cases:

To go deeper on defining and calling your own functions, see PHP Functions.

Conclusion

The header() function is your direct line to the HTTP response headers in PHP. The rules are simple: build the header string, call header() before any output, and exit after a redirect. With it you can redirect users, set content types, serve downloads, send status codes, and control caching — the building blocks of almost every dynamic PHP response.

Practice

Practice
What does the PHP header function do?
What does the PHP header function do?
Was this page helpful?