Wire / Cookie Banners / Article
┌── POST 09.15 · Cookie Banners · 7 min read

How Long Should Cookie Consent Last? Guidance, Library Defaults and Browser Caps

Regulators converge on six months, CMP libraries default to 120-365 days, and Safari deletes a JavaScript-set consent cookie after seven days without interaction. The sources, the source code, and how to make the lifetime you chose the one you get.

TL;DR

There is no statutory number. The guidance that exists clusters around six months: the CNIL calls keeping both consent and refusal for six months good practice, the Garante and the ICO both say not to re-ask after a refusal for six months, and Spain’s AEPD puts the ceiling on consent at 24 months. The libraries default to something else — 182 days in CookieConsent, 120 in Klaro’s code, 365 in tarteaucitron and c15t — and the browser then applies its own limit on top. In Safari, a consent cookie written by JavaScript is deleted after seven days without a click, tap or keypress on your site, whatever expiry you gave it.

“How long should the cookie banner remember the answer?” gets asked as a legal question, but in practice three separate layers decide it: what regulators say, what your consent library defaults to, and what the visitor’s browser actually keeps. They rarely agree. Here are all three as of 15 September 2026.

Layer one: what the guidance says

Neither the ePrivacy Directive nor the GDPR sets a duration. The ICO says so directly: “Neither PECR nor the UK GDPR set a specific time limit on consent.” What exists is regulator guidance, and it is fairly consistent.

  • CNIL (France). Recommendation of 17 September 2020, §39: keeping the choice, “tant le consentement que le refus” (consent and refusal alike), for six months “constitue une bonne pratique”. The CNIL frames this as good practice and says the right period depends on the site and its audience.
  • Garante (Italy). Cookie guidelines of 10 June 2021, §6.2: once a choice is recorded, the banner should not be shown again unless the processing changes significantly, the site cannot know whether a cookie was already stored (for example because the user deleted it), or “at least six months have elapsed since the banner was last presented”. Any one of the three is enough.
  • ICO (UK). Storage and access technologies guidance, last updated 29 April 2026: after a refusal, “we recommend that six months is a suitable timeframe to request fresh consent”. It also warns that a CMP’s default expiry is something to check rather than accept.
  • AEPD (Spain). Cookie guide, updated May 2024, §3.2.8: good practice is for consent to stay valid for no more than 24 months. We found no statement in it about waiting after a refusal.

The Digital Omnibus would turn part of this into law. Article 88a(4)(c) of the Commission’s proposal says that after a refusal the controller “shall not make a new request for consent for the same purpose for a period of at least six months”. It is a proposal. As of today the Parliament’s procedure file reads “Awaiting committee decision”.

The cookie that stores the choice is not itself the problem. The CNIL’s guidelines (§49) list trackers “conservant le choix exprimé par les utilisateurs” among those that can be exempt, and the ICO’s exceptions page says the same about consent-mechanism cookies.

Layer two: what the libraries default to

We read the source of the four most-used open-source consent libraries at their latest release tags.

Library (tag) Default lifetime Notes
vanilla-cookieconsent 3.1.0 182 days cookie.expiresAfterDays; can be a function of the accept type
Klaro 0.7.22 120 days in code The sample config.js sets 365, so copied configs usually say 365
tarteaucitron 1.34.0 365 days tarteaucitronForceExpire can shorten it, never lengthen
c15t 2.2.1 365 days defaultExpiryDays; also copied to localStorage

Three behaviours matter more than the headline numbers.

The clock starts at the choice, not the last visit

None of the four re-writes the consent cookie on a normal return visit. CookieConsent’s run() and Klaro’s constructor only read it, and CookieConsent writes again only when the choice actually changes. A visitor who accepted 182 days ago and came back yesterday sees the banner today.

tarteaucitron is the exception. If a service with needConsent: false is loaded — its bundled Matomo, Plausible and Crisp definitions are among them — the shared cookie is re-written on every page load, which pushes the expiry of every stored choice forward. On those sites, “365 days” means 365 days after the last visit.

localStorage mode can mean no expiry at all

Klaro’s storageMethod: 'localStorage' ignores cookieExpiresAfterDays. The store in src/stores.js is a plain setItem, with no timestamp and no check, so the choice is kept until the browser clears it. CookieConsent’s useLocalStorage does store an expirationTime and checks it on read.

c15t keeps both copies. If the cookie is missing but localStorage still holds the record, storage.ts re-creates the cookie with a fresh expiry.

Refusal and consent can have different lifetimes

Only CookieConsent exposes this directly:

CookieConsent.run({
  cookie: {
    // acceptType is 'all', 'necessary' or 'custom'
    expiresAfterDays: (acceptType) => acceptType === 'necessary' ? 182 : 365
  },
  // ...
});

The numbers are an example, not a recommendation. The point is that the period becomes a written decision rather than a default nobody chose.

Layer three: what the browser keeps

  • Chrome caps Expires and Max-Age at 400 days (since version 104), matching the RFC 6265bis draft. Matomo’s mtm_consent asks for 30 years and gets 400 days.
  • Brave caps cookies set by JavaScript at six months, the same as HTTP cookies, after removing its old seven-day cap in the 1.83 cycle. A 365-day consent cookie gets about half that.
  • Safari is the one that matters. WebKit’s tracking prevention documentation says ITP “deletes all cookies created in JavaScript and all other script-writeable storage after 7 days of no user interaction with the website”. User interaction means “a user click, tap, or keyboard entry”; scrolling does not count. If the visitor arrived through a link carrying tracking parameters, cookies set by JavaScript on that landing page are capped at 24 hours.

One caveat on the Safari figure. WebKit’s source also contains a longer deletion period, added in 2024, and Apple has not said which period shipping Safari applies to which sites. Seven days is the documented behaviour, and it is the one to plan for.

In practice, a reader who clicks “Reject all” and then comes back only to read, never clicking, can lose that refusal after a week of using Safari. localStorage does not escape it, because the same rule covers all script-writeable storage. We have covered two other Safari bugs that shorten consent cookies separately.

Making the number you chose the number you get

Set the consent cookie from your own server

The seven-day deletion applies to cookies created in JavaScript. A cookie in a Set-Cookie response header from your own origin is not covered by that rule. It is capped only when the response comes from a third-party CNAME or IP address. Echo the library’s cookie back from a first-party endpoint after each change:

// Express + cookie-parser: re-issue CookieConsent's cookie from the server
app.post('/consent/persist', (req, res) => {
  const raw = req.cookies['cc_cookie'];          // cookie-parser has decoded it
  if (!raw) return res.sendStatus(204);
  const { expirationTime } = JSON.parse(raw);    // the library stores this in the value
  const maxAge = Math.floor((expirationTime - Date.now()) / 1000);
  if (maxAge <= 0) return res.sendStatus(204);
  res.setHeader('Set-Cookie', `cc_cookie=${encodeURIComponent(raw)}; Max-Age=${maxAge}; ` +
    `Domain=${req.hostname}; Path=/; SameSite=Lax; Secure`);
  res.sendStatus(204);
});

Call it with fetch('/consent/persist', { method: 'POST' }) from onFirstConsent and onChange. The attributes have to match what the library writes. CookieConsent 3.1.0 sets Domain to the page’s hostname by default, and a header cookie without it would sit alongside the original as a second cc_cookie rather than replace it. Do not set HttpOnly, because the library still has to read the cookie. Any later write through document.cookie should be treated as a script-written cookie again, which is why the endpoint runs after every change. Serve it from the page’s own host, not a subdomain pointed at a third-party platform, or the seven-day cap on cloaked responses applies instead.

Store when, not just what

Put the decision timestamp inside the record, and re-ask based on that date rather than on whether the cookie still exists. A missing cookie tells you the visitor is unknown. It does not tell you they have never refused. That timestamp is also the field a proof-of-consent log needs.

Keep the tools in step

If the banner forgets after 182 days but an analytics tool keeps its own consent flag for 400, the two disagree for seven months. Matomo’s 30-year consent cookie is the common case. Expire or clear the downstream flags when the CMP record expires.

The expiry in your config and the expiry stored in the browser are often different numbers. Scan your site to see which cookies it sets and how long each one is kept with CookieInspector.

C
About the author
Consent Mode HQ
Editorial team at Consent Mode HQ
Read more by author ↗