Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools

PHP Cookies setcookie, $_COOKIE, Security: Tutorial, Examples, FAQs & Interview Tips

PHP Cookies

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.

How Cookies Work

  1. Server creates a cookie - PHP sends a Set-Cookie header in the response.
  2. Browser stores the cookie - The browser saves it according to its expiry, domain, path, and security rules.
  3. Browser sends it back - On matching future requests, the browser includes the cookie in the Cookie request header.
  4. PHP reads it - PHP exposes incoming cookies through the $_COOKIE superglobal.

Creating a Cookie with setcookie()

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.

Create a Basic Cookie
<?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.';
?>

Reading Cookies with $_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.

Read a Cookie
<?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');
?>

Cookie Parameters

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 setcookie() Options Array

Modern PHP supports an options array for setcookie(). This is clearer than passing many positional parameters, and it supports SameSite cleanly.

Secure Cookie Options
<?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.';
?>

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.

Session Cookies vs Persistent Cookies

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.

Session and Persistent Cookies
<?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',
]);
?>

Updating a Cookie

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.

Update a Cookie
<?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',
]);
?>

Deleting a Cookie

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.

Delete a Cookie
<?php
setcookie('theme', '', [
    'expires' => time() - 3600,
    'path' => '/',
    'samesite' => 'Lax',
]);

unset($_COOKIE['theme']);

echo 'Theme cookie deleted.';
?>

Practical Example: Remember Theme Preference

A common use of cookies is remembering a user's theme preference. The cookie stores only a safe preference value, not private account data.

Theme Preference
<?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>

Practical Example: Cookie Consent

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.

Cookie Consent
<?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; ?>

Cookie Security Rules

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 tl-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.

Signed Cookies

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.

Simple Signed Cookie
<?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;
?>

Cookies vs Sessions

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

Common Cookie Problems

  • Headers already sent: call setcookie() before output, or use output buffering carefully.
  • Cookie not visible immediately: read it on the next request or update $_COOKIE manually for the current request.
  • Delete does not work: use the same path and domain used when creating the cookie.
  • Secure cookie missing on localhost: a Secure cookie requires HTTPS in normal browser behavior.
  • Multiple cookies with same name: different paths or domains can create confusing duplicates.

Summary

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.

Key Takeaways
  • setcookie() sends a cookie through HTTP headers, so it must run before page output.
  • $_COOKIE contains cookies received from the browser on the current request.
  • A cookie set with setcookie() is usually readable from $_COOKIE on the next request.
  • Delete cookies by setting the same cookie name, path, and domain with an expiry time in the past.
  • Use HttpOnly, Secure, and SameSite for safer cookies.
  • Never store passwords or sensitive account data directly in cookies.
Common Mistakes to Avoid
WRONG Calling setcookie() after HTML output
RIGHT Call setcookie() before any output
Cookies are sent as headers. Once PHP sends body content, headers cannot be changed safely.
WRONG Trusting $_COOKIE values directly
RIGHT Validate and escape cookie values before use
Users can edit cookies in the browser, so cookie values must be treated as untrusted input.
WRONG Deleting a cookie with a different path
RIGHT Delete with the same name, path, and domain
Cookie identity includes path and domain. A mismatch can leave the original cookie in the browser.

Frequently Asked Questions

setcookie() sends a cookie to the browser for future requests. $_COOKIE 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.

HttpOnly 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.

Lax is a practical default for many website cookies. Strict is more restrictive. None is for third-party cookie use cases and must be combined with Secure.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.