PHP

How to Fix the “Headers Already Sent” Error in PHP

How to Fix the “Headers Already Sent” Error in PHP

When you work with PHP redirects, cookies, or sessions, you may face this common warning:

Warning: Cannot modify header information - headers already sent by (output started at /some/file.php:12) in /some/file.php on line 23

This usually happens when your code calls header() or setcookie() after PHP has already sent output (HTML/text) to the browser.

In this blog post, you’ll learn:

  • What “headers already sent” really means
  • The real reasons it happens
  • How to fix it correctly (with clean coding examples)
  • Best practices to avoid it forever

What Are Headers in PHP?

When a browser requests a page, the server responds in two parts:

  1. Headers (metadata):
    • Redirect location
    • Cookies
    • Content type (HTML/JSON)
    • Cache rules
  2. Body (actual output):
    • HTML
    • Text
    • JSON

PHP must send headers before the body.

So, if any output (even a space) is sent first, then later you try:

  • header("Location: ...")
  • setcookie(...)
  • session_start()

PHP throws the warning because headers are already locked.

Why This Error Happens (Most Common Reasons)

You Printed Output Before header() or setcookie():

Wrong:

<?php
echo "Hello"; // Output starts here
header("Location: dashboard.php"); // Now it's too late

Correct:

<?php
header("Location: dashboard.php");
exit;

Always use exit; after redirects to stop script execution.

Whitespace or Blank Line Before <?php:

Even one empty line before <?php counts as output.

Wrong (notice blank line at top):

<?php
header("Location: home.php");

Correct:

<?php
header("Location: home.php");
exit;

Closing ?> Tag in PHP-Only Files:

In pure PHP files (like config.php, functions.php) the closing ?> can accidentally output whitespace.

Risky:

<?php
// config.php
$siteName = "My Site";
?>

Best practice (remove ?>):

<?php
$siteName = "My Site";

Output from Included Files (include / require):

If an included file prints HTML before headers, your headers will fail.

Example:

<?php
require "header.php"; // outputs HTML
setcookie("user", "Ali", time() + 3600); // fails

Fix: Set cookies before loading templates:

<?php
setcookie("user", "Ali", time() + 3600, "/");
require "header.php";

UTF-8 BOM (Invisible Characters):

Some editors save files with a BOM (Byte Order Mark). Those invisible bytes are output before PHP runs.

Fix:

  • Re-save your file as UTF-8 without BOM
  • In VS Code: “Save with Encoding” → “UTF-8”

How to Find the Exact Source of the Problem

Read this part carefully:

output started at /some/file.php:12

This means output began at file.php line 12.
That is the real place to check, not only the line where header() fails.

At that line, look for:

  • echo, print
  • HTML outside PHP
  • spaces/blank lines
  • closing ?>
  • includes that output content

Correct Fix Patterns (With Proper Coding)

Redirect Before Any Output:

<?php
// redirect.php
if (!isset($_GET['ok'])) {
header("Location: login.php");
exit;
}echo "Welcome!"; // This is safe now because redirect already happened (or didn’t)

Correct Use of Cookies:

<?php
// Must be before any output
setcookie("theme", "dark", time() + 86400, "/");echo "Cookie is set!";

Correct Use of Sessions:

<?php
session_start(); // must be first$_SESSION['user'] = "Ali";header("Location: profile.php");
exit;

Fix Using Output Buffering (Useful for Old Projects)

If your project is large and it’s hard to control output order, use output buffering.

<?php
ob_start(); // start bufferingecho "<h1>Loading...</h1>"; // output buffered, not sent yetheader("Location: home.php");
exit;ob_end_flush();

Note: Buffering helps, but best practice is still to structure code correctly.

Best Practices to Avoid This Error Forever

Do these every time:

  • Put session_start(), setcookie(), and header() at the top
  • Never output HTML before redirects/cookies
  • Remove closing ?> from PHP-only files
  • Keep config/includes “silent” (no echo, no HTML)
  • Use exit; after header("Location: ...")

Full Example: Clean Login Redirect Script

<?php
session_start();// If user is not logged in, redirect
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}// Set a cookie safely
setcookie("visited", "yes", time() + 3600, "/");
?>
<!doctype html>
<html>
<head>
<title>Dashboard</title>
</head>
<body>
<h1>Welcome to Dashboard</h1>
</body>
</html>

This is a correct structure:
headers/cookies first → HTML after

Conclusion

The “Cannot modify header information headers already sent” warning happens because PHP must send headers before output, and your script is outputting something earlier (even invisible whitespace or BOM). The correct fix is to move header/cookie/session calls before output and clean up included files to avoid accidental output.

author-avatar

About MALIK SHAFI

Experienced PHP Developer with a strong background in building scalable web applications in the IT services sector. Proficient in PHP frameworks like Laravel and CodeIgniter, and front-end technologies, Skilled in MySQL database management, RESTful API integration, and working with AWS services such as EC2 and S3. Extensive hands-on experience with Nginx configuration on AWS EC2 instances, optimizing for performance and security.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments