PHP Cookies setcookie, $_COOKIE, Security is an important PHP topic because it shows up in real projects, debugging sessions, and interviews. Learn the meaning first, then connect it to a small working example so the rule does not stay abstract.
Focus on what problem PHP Cookies setcookie, $_COOKIE, Security solves, where developers usually make mistakes, and how to verify the result with output, behavior, or a small test.
A strong understanding of PHP Cookies setcookie, $_COOKIE, Security should include syntax, behavior, one realistic use case, one failure case, and one quick way to check your work.
PHP Cookies setcookie $_COOKIE Security should be studied as a practical PHP lesson, not as a label. Start by naming the input, the rule that changes the input, and the result a learner should be able to predict after reading the page.
In the php > cookies page, the notes should connect the definition with a working scenario, a mistake that beginners actually make, and the exact check that proves the fix. That makes the topic useful for coding, debugging, and interview revision.
A cookie is a small piece of text data stored in the user's browser and sent back to the server on later requests. PHP can create cookies, read cookies, update cookies, and delete cookies. Cookies are useful for remembering lightweight information such as theme preference, language choice, cookie consent, referral source, and non-sensitive user preferences.
Cookies are part of HTTP headers. That means PHP must send cookies before it sends any HTML, spaces, new lines, or other output to the browser. If output has already started, setcookie() cannot add the required Set-Cookie header.
The basic PHP function for creating cookies is setcookie(). A simple cookie needs a name, value, and optional expiry time. The cookie will not appear in $_COOKIE until the next request because $_COOKIE contains cookies received from the browser, not cookies you just scheduled to send.
<?php
// Must run before any HTML output.
// Cookie expires in 1 hour.
setcookie('username', 'Alice', time() + 3600);
// Cookie expires in 30 days.
setcookie('theme', 'dark', time() + (86400 * 30));
echo 'Cookies have been sent. Refresh the page to read them from $_COOKIE.';
?>
PHP stores incoming cookies in $_COOKIE, which is an associative array. Always check whether a cookie exists before reading it, and always escape cookie values before displaying them in HTML. Cookies are user-controlled data, so never trust them blindly.
<?php
$username = $_COOKIE['username'] ?? 'Guest';
$theme = $_COOKIE['theme'] ?? 'light';
echo 'Welcome, ' . htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
echo '<br>';
echo 'Theme: ' . htmlspecialchars($theme, ENT_QUOTES, 'UTF-8');
?>
A cookie is more than just a name and value. Its options decide how long it lasts, where it is sent, and how protected it is.
| Option | Meaning | Example |
|---|---|---|
| expires | Unix timestamp for when the cookie expires. | time() + 86400 |
| path | URL path where the cookie is available. | / for the whole site |
| domain | Domain that can receive the cookie. | example.com |
| secure | Send only over HTTPS. | true |
| httponly | Block JavaScript access to the cookie. | true |
| samesite | Controls cross-site cookie sending. | Lax, Strict, or None |
Modern PHP supports an options array for setcookie(). This is clearer than passing many positional parameters, and it supports SameSite cleanly.
Use SameSite=Lax for many normal website cookies. Use SameSite=Strict for stricter same-site behavior. Use SameSite=None only when a cookie must be sent in third-party contexts, and pair it with Secure.
<?php
setcookie('theme', 'dark', [
'expires' => time() + (86400 * 30), // 30 days
'path' => '/',
'domain' => '', // current host
'secure' => true, // HTTPS only
'httponly' => true, // unavailable to JavaScript
'samesite' => 'Lax', // good default for most sites
]);
echo 'Secure cookie sent.';
?>
A cookie without an expiry time is a session cookie. It is normally removed when the browser session ends. A cookie with an expiry time is a persistent cookie, so the browser can keep it until the expiry date.
<?php
// Session cookie: browser removes it when the browser session ends.
setcookie('temporary_notice', 'shown');
// Persistent cookie: browser keeps it for 90 days.
setcookie('language', 'en', [
'expires' => time() + (86400 * 90),
'path' => '/',
'samesite' => 'Lax',
]);
?>
To update a cookie, call setcookie() again with the same name, path, and domain. The browser replaces the old cookie with the new one. If the path or domain does not match, you may accidentally create a second cookie instead of replacing the first one.
<?php
// Original cookie.
setcookie('theme', 'light', [
'expires' => time() + (86400 * 30),
'path' => '/',
'samesite' => 'Lax',
]);
// Later, update the same cookie.
setcookie('theme', 'dark', [
'expires' => time() + (86400 * 30),
'path' => '/',
'samesite' => 'Lax',
]);
?>
To delete a cookie, set the same cookie name with an expiry time in the past. Use the same path and domain that were used when the cookie was created. You may also unset the value from $_COOKIE so the rest of the current request does not keep using the old value.
<?php
setcookie('theme', '', [
'expires' => time() - 3600,
'path' => '/',
'samesite' => 'Lax',
]);
unset($_COOKIE['theme']);
echo 'Theme cookie deleted.';
?>
A common use of cookies is remembering a user's theme preference. The cookie stores only a safe preference value, not private account data.
<?php
$allowedThemes = ['light', 'dark'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$theme = $_POST['theme'] ?? 'light';
if (!in_array($theme, $allowedThemes, true)) {
$theme = 'light';
}
setcookie('theme', $theme, [
'expires' => time() + (86400 * 365),
'path' => '/',
'secure' => !empty($_SERVER['HTTPS']),
'httponly' => true,
'samesite' => 'Lax',
]);
$_COOKIE['theme'] = $theme; // Use the new value during this request.
}
$currentTheme = $_COOKIE['theme'] ?? 'light';
if (!in_array($currentTheme, $allowedThemes, true)) {
$currentTheme = 'light';
}
?>
<body class="theme-<?= htmlspecialchars($currentTheme, ENT_QUOTES, 'UTF-8') ?>">
<form method="post">
<select name="theme">
<option value="light" <?= $currentTheme === 'light' ? 'selected' : '' ?>>Light</option>
<option value="dark" <?= $currentTheme === 'dark' ? 'selected' : '' ?>>Dark</option>
</select>
<button type="submit">Save theme</button>
</form>
</body>
Many sites store a small consent cookie after a user accepts a cookie banner. The example below stores only whether the banner has been accepted.
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['cookie_consent'] ?? '') === 'yes') {
setcookie('cookie_consent', 'yes', [
'expires' => time() + (86400 * 180),
'path' => '/',
'secure' => !empty($_SERVER['HTTPS']),
'httponly' => true,
'samesite' => 'Lax',
]);
$_COOKIE['cookie_consent'] = 'yes';
}
$hasConsent = ($_COOKIE['cookie_consent'] ?? '') === 'yes';
?>
<?php if (!$hasConsent): ?>
<form method="post" class="cookie-banner">
<p>We use cookies to remember your preferences.</p>
<input type="hidden" name="cookie_consent" value="yes">
<button type="submit">Accept</button>
</form>
<?php endif; ?>
Cookies are stored on the client, so users can inspect, edit, delete, or fake them. Treat every cookie value as untrusted input. Do not store passwords, raw tokens, credit card numbers, private profile data, or authorization decisions directly in cookies.
| Rule | Why it matters |
|---|---|
| Use HttpOnly | Reduces the chance that JavaScript-based XSS can read the cookie. |
| Use Secure | Sends the cookie only over HTTPS. |
| Use SameSite | Helps control whether cookies are sent with cross-site requests. |
| Validate values | A cookie is user input. Check it before trusting it. |
| Keep values small | Cookies are sent with requests, so large cookies slow down traffic. |
| Use sessions for sensitive state | Sessions store sensitive data server-side and only keep a session ID in the browser. |
If you need to detect whether a user modified a cookie, sign the value with an HMAC. This does not hide the value, but it lets your application reject tampered data. For private data, use server-side sessions or carefully designed encryption instead.
<?php
$secret = 'replace-this-with-a-long-random-secret';
function signCookieValue(string $value, string $secret): string
{
$signature = hash_hmac('sha256', $value, $secret);
return $value . '.' . $signature;
}
function readSignedCookie(string $cookie, string $secret): ?string
{
$parts = explode('.', $cookie, 2);
if (count($parts) !== 2) {
return null;
}
[$value, $signature] = $parts;
$expected = hash_hmac('sha256', $value, $secret);
return hash_equals($expected, $signature) ? $value : null;
}
setcookie('referrer', signCookieValue('newsletter', $secret), [
'expires' => time() + 86400,
'path' => '/',
'secure' => !empty($_SERVER['HTTPS']),
'httponly' => true,
'samesite' => 'Lax',
]);
$referrer = isset($_COOKIE['referrer'])
? readSignedCookie($_COOKIE['referrer'], $secret)
: null;
?>
| Feature | Cookies | Sessions |
|---|---|---|
| Storage location | Browser | Server |
| Best for | Preferences, consent, lightweight non-sensitive values | Login state, cart data, private user state |
| User can edit it? | Yes | Only the session ID is in the browser |
| Size | Small values only | Can hold more data, depending on storage |
| PHP API | setcookie(), $_COOKIE | session_start(), $_SESSION |
PHP cookies are best for small, non-sensitive values that the browser should remember between requests. Use setcookie() before output to create, update, or delete cookies, and read incoming values from $_COOKIE. Always treat cookie data as untrusted input, escape values before display, and use security flags such as HttpOnly, Secure, and SameSite for safer behavior.
<?php
$value = 'ready';
if ($value !== '') {
echo 'PHP Cookies setcookie $_COOKIE Security: normal path';
}
<?php
$items = [];
echo empty($items) ? 'PHP Cookies setcookie $_COOKIE Security: no records found' : $items[0];
Memorizing PHP Cookies setcookie $_COOKIE Security without the situation where it is useful.
Connect PHP Cookies setcookie $_COOKIE Security to a concrete PHP task.
Testing PHP Cookies setcookie $_COOKIE Security only with the perfect input.
Include empty, missing, duplicate, incompatible, or failed cases when relevant.
Changing code before reading the visible symptom or error message.
Inspect the output, state, configuration, or stack trace connected to PHP Cookies setcookie $_COOKIE Security.
Memorizing PHP Cookies setcookie $_COOKIE Security without the situation where it is useful.
Connect PHP Cookies setcookie $_COOKIE Security to a concrete PHP task.
<code>setcookie()</code> sends a cookie to the browser for future requests. <code>$_COOKIE</code> contains cookies that arrived with the current request, so the new value normally appears after the next page load.
No. Never store passwords or sensitive account data in cookies. Use server-side sessions for login state and store only a session ID in the browser.
<code>HttpOnly</code> tells the browser not to expose the cookie to JavaScript. This helps reduce the impact of some XSS attacks, but it does not replace output escaping and other security practices.
<code>Lax</code> is a practical default for many website cookies. <code>Strict</code> is more restrictive. <code>None</code> is for third-party cookie use cases and must be combined with <code>Secure</code>.
Explore 500+ free tutorials across 20+ languages and frameworks.