Session vs Cookie in PHP: Difference with Login Example
A cookie lives in the user's browser (user can see/edit it); a session lives on the server with only an ID cookie in the browser. Login example and security rules.
The locker analogy
A cookie is a chit in the visitor's own pocket — the site writes something ("theme=dark") and hands it to the browser; the visitor carries it, can open it, read it, even rewrite it. A session is a locker at the site's own office — the valuables (user_id, role, cart) stay on the server; the visitor's pocket holds only the locker number (the session ID cookie, PHPSESSID). Whatever matters for security must live in the locker, never in the pocket.
Both in code — the login example
<?php
// ---------- SESSION: the right way to log someone in ----------
session_start(); // must be the FIRST thing (before any HTML!)
// after verifying username+password from DB:
$_SESSION['user_id'] = 27; // stored ON SERVER
$_SESSION['role'] = 'admin';
// on every protected page:
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php'); // not logged in -> out
exit;
}
// logout:
session_start();
session_destroy(); // locker emptied
?>
<?php
// ---------- COOKIE: the right way to remember a preference ----------
setcookie('theme', 'dark', time() + 86400*30, '/'); // 30 days, whole site
// NOTE: setcookie() also must run before any HTML output!
// on next visits:
$theme = $_COOKIE['theme'] ?? 'light'; // read what the browser carried back
echo "Theme: " . htmlspecialchars($theme);
?>
The security point that decides interviews
// NEVER do this:
setcookie('is_admin', '1'); // user opens DevTools -> Application ->
// Cookies -> changes 0 to 1 -> "admin"!
// ALWAYS do this:
$_SESSION['is_admin'] = true; // lives on server - user cannot touch it
Cookies are fully editable by the user in any browser's DevTools in ten seconds. Any trust decision (logged in? admin? user_id?) stored in a cookie is an open invitation. Sessions are safe from this because the browser only holds the random session ID — the actual data never leaves the server.
Comparison table
| Point | Cookie | Session |
|---|---|---|
| Data lives | User's browser | Server (file/DB); browser keeps only ID |
| User can read/edit | ✅ Yes (DevTools) | ❌ No |
| Lifetime | You set expiry (days/months) | Ends on browser close / timeout (~24 min default) |
| Size limit | ~4KB per cookie | Practically large |
| Sent with every request | ✅ Yes (adds weight) | Only the small ID |
| Start with | setcookie() | session_start() |
| Read with | $_COOKIE | $_SESSION |
| Best for | Theme, language, "remember me" token | Login state, cart, OTP verification, roles |
Two traps every PHP beginner hits
- "Headers already sent" error: both
session_start()andsetcookie()travel in HTTP headers, so they must run before any output — even a single space before<?phptriggers it. Rule: session_start() is line 1. - Cookie not visible immediately: setcookie() sends the cookie with this response; $_COOKIE gets filled from the request — so the value appears only from the next page load. Not a bug; that is how the round-trip works.
- Interview line: "Cookie = client-side, user-editable, long-lived — for preferences. Session = server-side, tamper-proof, short-lived — for identity. They cooperate: the session ID itself rides in a cookie."
Locker वाली analogy
Cookie visitor की अपनी जेब की पर्ची है — site कुछ लिखकर ("theme=dark") browser को थमा देती है; visitor उसे रखता है, खोल सकता है, पढ़ सकता है, यहां तक कि बदल भी सकता है. Session site के अपने office का locker है — कीमती चीज़ें (user_id, role, cart) server पर रहती हैं; visitor की जेब में सिर्फ locker number (session ID cookie, PHPSESSID). Security के लिए जो भी ज़रूरी है वह locker में रहे, जेब में कभी नहीं.
दोनों code में — login example
<?php
// ---------- SESSION: login कराने का सही तरीका ----------
session_start(); // सबसे PEHLI चीज़ (किसी भी HTML से पहले!)
// DB से username+password verify करने के बाद:
$_SESSION['user_id'] = 27; // SERVER par stored
$_SESSION['role'] = 'admin';
// हर protected page पर:
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php'); // login नहीं -> बाहर
exit;
}
// logout:
session_start();
session_destroy(); // locker खाली
?>
<?php
// ---------- COOKIE: preference याद रखने का सही तरीका ----------
setcookie('theme', 'dark', time() + 86400*30, '/'); // 30 दिन, पूरी site
// NOTE: setcookie() भी किसी भी HTML output से पहले चलना चाहिए!
// अगली visits पर:
$theme = $_COOKIE['theme'] ?? 'light'; // browser जो वापस लाया वह पढ़ो
echo "Theme: " . htmlspecialchars($theme);
?>
वह security point जो interview तय करता है
// ऐसा KABHI न करें:
setcookie('is_admin', '1'); // user ने DevTools खोला -> Application ->
// Cookies -> 0 को 1 किया -> "admin"!
// HAMESHA ऐसा करें:
$_SESSION['is_admin'] = true; // server पर रहता है - user छू नहीं सकता
Cookies किसी भी browser के DevTools में दस second में user पूरी तरह edit कर सकता है. कोई भी trust का decision (logged in? admin? user_id?) cookie में रखना खुला निमंत्रण है. Sessions इससे safe हैं क्योंकि browser के पास सिर्फ random session ID है — असली data server से बाहर जाता ही नहीं.
Comparison table
| Point | Cookie | Session |
|---|---|---|
| Data रहता है | User के browser में | Server पर (file/DB); browser में सिर्फ ID |
| User पढ़/बदल सकता है | ✅ हां (DevTools) | ❌ नहीं |
| Lifetime | आप expiry set करते हैं (दिन/महीने) | Browser बंद / timeout पर खत्म (~24 min default) |
| Size limit | ~4KB प्रति cookie | Practically बड़ा |
| हर request के साथ जाता है | ✅ हां (वज़न बढ़ाता है) | सिर्फ छोटी ID |
| शुरू करें | setcookie() | session_start() |
| पढ़ें | $_COOKIE | $_SESSION |
| Best for | Theme, language, "remember me" token | Login state, cart, OTP verification, roles |
दो traps जो हर PHP beginner को लगते हैं
- "Headers already sent" error:
session_start()औरsetcookie()दोनों HTTP headers में जाते हैं, इसलिए किसी भी output से पहले चलने चाहिए —<?phpसे पहले एक space भी यह error दे देता है. Rule: session_start() line 1 पर. - Cookie तुरंत नहीं दिखती: setcookie() cookie को इस response के साथ भेजता है; $_COOKIE request से भरता है — इसलिए value अगले page load से दिखती है. Bug नहीं; round-trip ऐसे ही काम करता है.
- Interview line: "Cookie = client-side, user-editable, लंबी उम्र — preferences के लिए. Session = server-side, tamper-proof, छोटी उम्र — identity के लिए. दोनों साथ काम करते हैं: session ID खुद cookie में सफर करती है."
Frequently Asked Questions
What is the difference between session and cookie?
A cookie stores data in the user's browser where the user can read and edit it; a session stores data on the server with only a random session ID kept in a browser cookie — so sensitive data like login state belongs in sessions.
Why should login status never be stored in a cookie?
Because cookies are fully editable in browser DevTools — a user could change is_admin from 0 to 1; session data lives on the server where the user cannot modify it.
Why does session_start() give a headers already sent error?
session_start() sends an HTTP header, and headers must go before any output — even one space or blank line before <?php causes the error, so call it as the very first statement.