À propos de ce cours
Découvrez les cookies : ce qu'ils sont, comment ils circulent entre le navigateur et le serveur (Set-Cookie et Cookie), et comment les créer, lire, modifier et supprimer en JavaScript avec document.cookie. La leçon détaille les attributs max-age, path, Secure, SameSite et HttpOnly, propose une petite bibliothèque de fonctions et un bandeau de consentement complet, rappelle les obligations légales, et présente l'actualité : maintien des cookies tiers dans Chrome et Cookie Store API, Baseline depuis 2025. Avec des activités corrigées.
-
Objectifs
- Comprendre ce qu'est un cookie, comment il circule entre le navigateur et le serveur, et à quoi il sert.
- Créer, lire, modifier et supprimer un cookie en JavaScript avec
document.cookie. - Choisir les bons attributs :
max-age,path,Secure,SameSite, et comprendreHttpOnly. - Connaître les règles de consentement et la Cookie Store API, l'API moderne des cookies.
-
Le stockage dans le navigateur : vue d'ensemble
- Une page web perd toutes ses variables JavaScript dès qu'on la recharge. Pour se souvenir d'un thème, d'un panier ou d'une liste de tâches, il faut stocker les données quelque part.
- Le navigateur propose quatre solutions, étudiées dans ce chapitre : les cookies (cette leçon), le localStorage et le sessionStorage (leçon 2) et IndexedDB (leçon 3).
- Toutes ces données sont rangées par site: un site ne peut pas lire les données d'un autre site.

-
Qu'est-ce qu'un cookie ?
- Un cookie est un petit texte (environ 4 Ko au maximum) de la forme
nom=valeur, enregistré par le navigateur pour un site donné. - Inventés en 1994 par Lou Montulli, chez Netscape, ils servaient à mémoriser le contenu d'un panier. Le protocole HTTP n'ayant aucune mémoire, il fallait un moyen de reconnaître un visiteur d'une page à l'autre.
- Leur particularité : le navigateur les renvoie automatiquement au serveur à chaque requête vers le site. C'est ce qui les rend indispensables pour les sessions (rester connecté), et c'est aussi leur défaut : des cookies trop gros alourdissent chaque échange.
- Usages principaux :
Usage Exemple Qui le crée ? Session Identifiant qui prouve que vous êtes connecté Le serveur (en HttpOnly)Préférences Langue, thème, ville choisie Le serveur ou JavaScript Consentement Choix de l'utilisateur dans le bandeau cookies JavaScript Mesure d'audience, publicité Statistiques de visite, suivi publicitaire Souvent un site tiers - Un cookie propriétaire (first-party) appartient au site visité. Un cookie tiers (third-party) est déposé par un autre domaine présent dans la page (régie publicitaire, bouton de réseau social) et permet de suivre l'internaute de site en site.
- Un cookie est un petit texte (environ 4 Ko au maximum) de la forme
-
Comment un cookie circule

- Le serveur dépose un cookie avec l'en-tête de réponse
Set-Cookie. JavaScript peut aussi en créer avecdocument.cookie. - Ensuite, à chaque requête vers ce site, le navigateur ajoute l'en-tête
Cookieavec tous les cookies concernés. - Pour les voir : DevTools (F12) → onglet Application → Storage → Cookies. Vous pouvez les modifier ou les supprimer à la main. Dans l'onglet Réseau, cliquez sur une requête pour voir les en-têtes
CookieetSet-Cookie.
document.cookie : une propriété un peu spéciale
- En lecture,
document.cookierenvoie tous les cookies accessibles, dans une seule chaîne :"theme=sombre; consentement=oui". Les attributs (durée, chemin…) ne sont pas visibles. - En écriture, une affectation n'écrase pas tout : elle ajoute ou remplace un seul cookie, avec ses attributs.
document.cookie = "theme=sombre; max-age=31536000; path=/; SameSite=Lax";
document.cookie = "langue=fr; max-age=31536000; path=/; SameSite=Lax";
console.log(document.cookie); // "theme=sombre; langue=fr"
// Modifier : on réécrit le même nom (avec le même path)
document.cookie = "theme=clair; max-age=31536000; path=/; SameSite=Lax";
// Supprimer : durée de vie à 0
document.cookie = "langue=; max-age=0; path=/";
- Les caractères
;,,, les espaces et les accents sont interdits dans la valeur : on les encode avecencodeURIComponent()et on les décode avecdecodeURIComponent().
-
Les attributs d'un cookie
-
Une petite bibliothèque de fonctions
| Attribut | Rôle | Conseil |
|---|---|---|
max-age=3600 | Durée de vie en secondes. Sans max-age ni expires, c'est un cookie de session, supprimé à la fermeture du navigateur. | Préférez max-age à expires (date au format UTC, plus pénible à écrire). |
path=/ | Pages du site concernées. Par défaut : le dossier de la page courante. | Mettez path=/ pour un cookie valable sur tout le site. |
domain=centre.tn | Rend le cookie visible aussi sur les sous-domaines (cours.centre.tn). | À omettre dans la plupart des cas. |
Secure | Le cookie n'est envoyé qu'en HTTPS. | Toujours en production. |
SameSite=Lax | Contrôle l'envoi du cookie quand la requête vient d'un autre site: Strict (jamais), Lax (seulement en suivant un lien), None (toujours, avec Secure obligatoire). | Lax: protège contre les attaques CSRF. Chrome l'applique par défaut. |
HttpOnly | Le cookie est invisible pour JavaScript: document.cookie ne le montre pas. | Ne peut être posé que par le serveur. Indispensable pour les sessions : une faille XSS ne pourra pas voler l'identifiant. |
Manipuler directement la chaîne document.cookie est source d'erreurs. Voici quatre fonctions réutilisables, cookies.js:
// Petite bibliothèque pour lire et écrire des cookies
function ecrireCookie(nom, valeur, options = {}) {
const {
jours = 30,
chemin = "/",
sameSite = "Lax",
secure = location.protocol === "https:",
} = options;
let cookie = `${encodeURIComponent(nom)}=${encodeURIComponent(valeur)}`;
cookie += `; max-age=${jours * 24 * 60 * 60}`;
cookie += `; path=${chemin}`;
cookie += `; SameSite=${sameSite}`;
if (secure) {
cookie += "; Secure";
}
document.cookie = cookie; // ajoute ou remplace UN cookie, n'efface pas les autres
}
function lireCookie(nom) {
const prefixe = `${encodeURIComponent(nom)}=`;
const trouve = document.cookie.split("; ").find((morceau) => morceau.startsWith(prefixe));
return trouve ? decodeURIComponent(trouve.slice(prefixe.length)) : null;
}
function supprimerCookie(nom, chemin = "/") {
// même nom et même chemin, avec une durée de vie nulle
document.cookie = `${encodeURIComponent(nom)}=; max-age=0; path=${chemin}`;
}
function tousLesCookies() {
if (document.cookie === "") {
return {};
}
return Object.fromEntries(
document.cookie.split("; ").map((morceau) => {
const position = morceau.indexOf("=");
return [
decodeURIComponent(morceau.slice(0, position)),
decodeURIComponent(morceau.slice(position + 1)),
];
}),
);
}
lireCookie()découpe la chaîne sur"; "et cherche le morceau qui commence exactement parnom=(pour ne pas confondrethemeettheme2).- Pour supprimer un cookie, il faut indiquer le même
pathqu'à sa création, sinon le navigateur considère qu'il s'agit d'un autre cookie.
Exemple complet : un bandeau de consentement
La page mémorise le prénom du visiteur dans un cookie, seulement s'il l'a accepté. Son choix est lui-même conservé dans un cookie consentement, pour ne pas lui reposer la question à chaque visite.
index.html:
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>Bandeau de consentement</title>
<link rel="stylesheet" href="style.css" />
<script src="cookies.js" defer></script>
<script src="consentement.js" defer></script>
</head>
<body>
<h1>Centre de formation</h1>
<p id="bonjour"></p>
<label>
Votre prénom :
<input id="prenom" />
</label>
<button id="btn-memoriser" type="button">Mémoriser</button>
<p><button id="btn-gerer" type="button">Gérer les cookies</button></p>
<div id="bandeau" class="bandeau" hidden>
<p>
Ce site utilise un cookie pour mémoriser votre prénom. Aucune donnée n'est partagée avec des
tiers.
</p>
<button id="btn-refuser" type="button">Refuser</button>
<button id="btn-accepter" type="button">Accepter</button>
</div>
</body>
</html>
style.css:
.bandeau {
position: fixed;
inset: auto 0 0 0;
padding: 16px 24px;
background: #1f2a3a;
color: #fff;
display: flex;
gap: 12px;
align-items: center;
}
.bandeau p {
flex: 1;
margin: 0;
}
/* sans cette règle, display: flex l'emporterait sur l'attribut hidden */
.bandeau[hidden] {
display: none;
}
consentement.js:
const bandeau = document.getElementById("bandeau");
const bonjour = document.getElementById("bonjour");
function afficherBonjour() {
const prenom = lireCookie("prenom");
bonjour.textContent = prenom ? `Bon retour parmi nous, ${prenom} !` : "Bienvenue !";
}
function choisir(accepte) {
// le choix lui-même est mémorisé 6 mois, qu'il soit positif ou négatif
ecrireCookie("consentement", accepte ? "oui" : "non", { jours: 182 });
if (!accepte) {
supprimerCookie("prenom");
}
bandeau.hidden = true;
afficherBonjour();
}
document.getElementById("btn-accepter").addEventListener("click", () => choisir(true));
document.getElementById("btn-refuser").addEventListener("click", () => choisir(false));
document.getElementById("btn-gerer").addEventListener("click", () => (bandeau.hidden = false));
document.getElementById("btn-memoriser").addEventListener("click", () => {
const prenom = document.getElementById("prenom").value.trim();
if (lireCookie("consentement") !== "oui") {
bandeau.hidden = false; // on redemande l'accord avant de déposer le cookie
return;
}
if (prenom) {
ecrireCookie("prenom", prenom, { jours: 30 });
afficherBonjour();
}
});
bandeau.hidden = lireCookie("consentement") !== null;
afficherBonjour();
- Le refus doit être aussi simple que l'acceptation : deux boutons de même importance, et un bouton « Gérer les cookies » pour changer d'avis.
- En cas de refus, on supprime le cookie
prenomdéjà déposé. - Remarquez la règle
.bandeau[hidden]: undisplay: flexécrit en CSS l'emporte sur l'attributhidden, piège très courant.
Cookies et loi
- En Europe, le RGPD et la directive ePrivacy imposent de demander l'accord de l'internaute avant de déposer des cookies qui ne sont pas strictement nécessaires (publicité, mesure d'audience non anonyme, réseaux sociaux). Les cookies indispensables (session, panier, mémorisation du choix de consentement) en sont dispensés.
- En Tunisie, la loi organique n° 2004-63 sur la protection des données personnelles, contrôlée par l'INPDP, impose elle aussi d'informer les personnes et de recueillir leur consentement.
- Bonnes pratiques : expliquer clairement à quoi sert chaque cookie, permettre de refuser aussi facilement que d'accepter, et redemander l'accord après quelques mois.
Actualités : cookies tiers et Cookie Store API
- Cookies tiers : Safari, Firefox et Brave les bloquent déjà par défaut. Google, qui prévoyait depuis 2019 de les supprimer de Chrome, a renoncé: le 22 avril 2025, il a confirmé que Chrome les garderait, l'utilisateur pouvant les bloquer dans ses paramètres de confidentialité, et les API qui devaient les remplacer (Privacy Sandbox) ont été retirées en octobre 2025. Ce choix ne change rien aux obligations de consentement, qui viennent de la loi et non du navigateur.
- Cookie Store API : une API moderne, asynchrone (avec des promesses), utilisable aussi dans les Service Workers. Elle est disponible dans tous les navigateurs récents (Baseline) depuis juin 2025 : Chrome 87, Safari 18.4 et Firefox 140. Comme les autres API récentes, elle exige un contexte sécurisé (HTTPS ou localhost).
// La même chose avec la Cookie Store API (asynchrone, HTTPS ou localhost)
await cookieStore.set({
name: "theme",
value: "sombre",
expires: Date.now() + 365 * 24 * 60 * 60 * 1000, // en millisecondes
sameSite: "lax",
});
const cookie = await cookieStore.get("theme"); // { name: "theme", value: "sombre", ... } ou null
console.log(cookie?.value);
await cookieStore.delete("theme");
// Être prévenu de chaque changement de cookie
cookieStore.addEventListener("change", (event) => {
for (const modifie of event.changed) {
console.log("modifié :", modifie.name, modifie.value);
}
for (const supprime of event.deleted) {
console.log("supprimé :", supprime.name);
}
});
- Plus besoin de découper une chaîne ni de calculer
max-age:get(),set()etdelete()font le travail, et l'événementchangesignale toute modification. Gardezdocument.cookiepour les navigateurs anciens.
Cookies ou autre chose ?
- Utilisez un cookie quand le serveur a besoin de la donnée à chaque requête : session, langue ou thème choisi pour générer la page dans le bon style dès son envoi.
- Pour des données qui ne servent qu'à JavaScript (une liste de tâches, un brouillon), préférez le localStorage: plus de place, une API plus simple, et rien n'est envoyé au serveur (leçon suivante).
- Ne stockez jamais de mot de passe ni de donnée sensible dans un cookie lisible par JavaScript.
Activités
Activité 1 : explorer les cookies
- Ouvrez un site d'information, puis DevTools → Application → Cookies. Combien de cookies voyez-vous ? Combien appartiennent à d'autres domaines (cookies tiers) ?
- Repérez un cookie marqué
HttpOnly. Tapezdocument.cookiedans la console : apparaît-il ?
Activité 2 : le bandeau de consentement
- Dans un dépôt GitHub
js-stockage-navigateur, dossiercookies, reproduisez l'exemple complet et testez-le avec Live Server. - Vérifiez dans DevTools la date d'expiration des cookies
prenometconsentement. - Ajoutez une liste déroulante « Langue » (français, anglais, arabe) mémorisée dans un cookie
langue, et affichez le message d'accueil dans la langue choisie.
Activité 3 : compteur de visites
- Avec un cookie
visites(durée : 1 an), affichez « C'est votre 1re visite », puis « C'est votre 5e visite »… - Ajoutez un cookie
dernierequi mémorise la date de la dernière visite et affichez « Dernière visite : il y a 3 jours ».
Activité 4 : questions
- Que se passe-t-il si l'on écrit
document.cookie = "a=1"puisdocument.cookie = "b=2"? Que contientdocument.cookie? - Pourquoi un identifiant de session doit-il être
HttpOnly? - Quelle est la durée de vie d'un cookie créé sans
max-ageniexpires? - Pourquoi est-il déconseillé de stocker une liste de 200 tâches dans un cookie ?
Corrigés. Activité 4 :
document.cookie vaut "a=1; b=2", car chaque affectation ajoute ou remplace un seul cookie ; avec HttpOnly, un script injecté par une faille XSS ne peut pas lire l'identifiant et usurper la session ; c'est un cookie de session, supprimé à la fermeture du navigateur ; un cookie est limité à environ 4 Ko et il est renvoyé au serveur à chaque requête, ce qui alourdit inutilement les échanges : le localStorage est fait pour cela. Activité 3 : const visites = Number(lireCookie("visites") ?? 0) + 1; puis ecrireCookie("visites", visites, { jours: 365 });. À retenir
- Un cookie est un petit texte
nom=valeurrenvoyé au serveur à chaque requête. document.cookie = "nom=valeur; max-age=…; path=/; SameSite=Lax"ajoute ou remplace un cookie ;max-age=0le supprime.- Encodez les valeurs avec
encodeURIComponent(); utilisezSecureetSameSite; les sessions sont enHttpOnly, posées par le serveur. - Consentement obligatoire pour les cookies non indispensables ; la Cookie Store API (Baseline depuis 2025) modernise leur manipulation.
Sources : MDN Web Docs, web.dev, CNIL, INPDP.