A cookie is a small name-value pair stored by the browser and sent with later matching requests. PHP sends cookie instructions in response headers.
Cookie values are client controlled. Use them for preferences or opaque identifiers, not as trusted authorization state or secret storage.
setcookie() must run before response output. A newly set cookie normally appears in $_COOKIE on the next request because $_COOKIE describes the current request.
<?php
setcookie('theme', 'dark', [
'expires' => time() + 60 * 60 * 24 * 30,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
$theme = $_COOKIE['theme'] ?? 'light';
| Option | Purpose |
|---|---|
| expires | Controls persistent lifetime; omit for a session cookie |
| path | Limits which URL paths receive the cookie |
| domain | Controls matching hosts; omit unless subdomain sharing is required |
| secure | Send only over HTTPS |
| httponly | Hide from browser JavaScript |
| samesite | Restrict cross-site sending behavior |
Updating means sending the same name, path, and domain with a new value. Deleting means sending matching scope attributes with an expiration in the past.
<?php
setcookie('theme', '', [
'expires' => time() - 3600,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
| Symptom | Check |
|---|---|
| Headers already sent | Output occurred before setcookie() |
| Cookie missing on localhost HTTP | Secure is true but the request is not HTTPS |
| Delete did not work | Path or domain differs from the original cookie |
| New value not in $_COOKIE immediately | It will arrive on the next matching request |
SameSite reduces some cross-site requests but does not replace CSRF tokens for sensitive state changes. HttpOnly limits script access but does not stop the browser from sending the cookie. Secure protects transport only when every relevant request uses HTTPS.
A signed cookie can reveal its value while detecting changes; encryption is required when the value itself must be confidential. For authentication, prefer an opaque random identifier backed by server-side state rather than encoding permissions into a browser-controlled value.
0 of 2 checked
Try this next
0 of 2 completed
Explore 500+ free tutorials across 20+ languages and frameworks.