cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Cookies

Learn how browser cookies store small values, travel with requests, and use attributes like Expires, Max-Age, SameSite, Secure, and HttpOnly.

By the end, you’ll be able to
  • 01
    Read and write cookies safelyUse document.cookie, encoding, updating, and deletion without confusing attributes for readable data.
  • 02
    Choose the right attributesExplain when Max-Age, Expires, Path, Domain, SameSite, Secure, and HttpOnly matter.
  • 03
    Pick the right storageDecide when a cookie, localStorage, or neither belongs in a real app.

Cookies in one minute

A cookie is a tiny name=value record that a browser stores for a site. Unlike a normal variable, a matching cookie can be sent back to the server automatically on future requests. That one idea powers login sessions, language choices, A/B test buckets, and consent flags.

Cookies are not general-purpose storage. They are small, string-based, and they ride along with requests. That is useful when the server needs the value, and wasteful or risky when it does not. A typical practical limit is around 4 KB per cookie, but browser rules vary, so keep cookies boring and tiny.

Real-life analogyA cookie is a hand stamp at an event

At an event, staff stamp your hand once and check it when you return. Cookies work similarly: a server gives the browser a value, and the browser sends it again when the request matches the cookie rules.

In real life: Staff stamp your hand
In JavaScript: The server sends Set-Cookie: session=abc
In real life: The stamp stays with you
In JavaScript: The browser stores the cookie
In real life: Staff check it when you return
In JavaScript: The browser sends Cookie: session=abc on matching requests
In real life: Staff recognize the stamp
In JavaScript: The server recognizes your browser or session

Where the analogy stops: A hand stamp shows a person returned. A cookie only shows that a browser sent a value, so servers still need security checks.

Cookie ideas you will use throughout the lesson
IdeaMeaningWhy it matters
ValueA string like theme=darkThe part JavaScript may read if the cookie is not HttpOnly.
AttributesRules like Max-Age, Path, SameSite, SecureThey control lifetime and sending, but are not read back through document.cookie.
Automatic sendingBrowser adds matching cookies to requestsGreat for sessions; bad for large data.
VisibilityNormal cookies are readable; HttpOnly cookies are notNever store secrets in JavaScript-readable cookies.

The rest of this lesson makes each of those rows concrete. You will write real demo cookies on this site, inspect the odd document.cookie API, simulate SameSite decisions, and decide when cookies are the wrong tool.

Expires & Max-Age: how long the ticket works

LIFETIME

A cookie without Expires or Max-Age is a session cookie. The browser may keep it until the browsing session ends. To make the lifetime explicit, use one of these attributes:

Cookie lifetime attributes
AttributeExampleMeaning
Max-AgeMax-Age=3600Valid for 3,600 seconds from now. If both attributes exist, this wins.
ExpiresExpires=Wed, 21 Oct 2030 07:28:00 GMTValid until an absolute HTTP date. Use the Date and time lesson for safe date handling.
DeleteMax-Age=0Overwrite the same name, path, and domain with an expired lifetime.

When you create an Expires string, use a real date formatted for HTTP, often from date.toUTCString(). If you need a refresher, revisit the Date & time lesson. For most app code, Max-Age is easier because it is just seconds from now.

Real-life analogyAttributes are rules on the hand stamp

A hand stamp can say it is valid only today or only in one area. Cookie attributes decide where and when the browser may use the value.

In real life: Valid only today
In JavaScript: Expires or Max-Age
In real life: Valid in one event area
In JavaScript: Path and Domain
In real life: Checked only at secure entrances
In JavaScript: Secure
In real life: Hidden from visitors
In JavaScript: HttpOnly

Where the analogy stops: A hand stamp is visible. HttpOnly cookies are deliberately hidden from JavaScript, though the browser can still send them.

SameSite: should another site be allowed to send your ticket?

SIMULATOR

SameSite is a request-sending rule. It helps reduce CSRF (cross-site request forgery), where a malicious site tries to make your browser submit a request to a site where you are already signed in. The browser decides whether the cookie rides along.

  • Strict: send only for same-site requests.
  • Lax: send for same-site requests and top-level cross-site GET navigations, such as normal links. Most modern browsers treat a missing SameSite as Lax-like.
  • None: allow cross-site sending, but modern browsers require Secure. Third-party-cookie restrictions may still block tracking-style cases.
SameSite simulator
DecisionCookie blocked
SameSiteLax
ScenarioCross-site POST form
Try it yourself

Lax blocks cross-site POST forms, iframes, images, and fetch-like subrequests to reduce CSRF risk.

A pure model of common SameSite behavior. Browsers also layer on third-party-cookie restrictions, so cross-site tracking cookies may be blocked even when this says sent.

Secure & HttpOnly: transport and visibility

SAFETY

Secure and HttpOnly solve different problems. Secure says the cookie is only sent over HTTPS. Localhost behavior has varied across browser features, so for real applications treat Secure cookies as HTTPS-only. HttpOnly says JavaScript cannot read the cookie at all.

Server Set-Cookie headersHTTP
Set-Cookie: session=abc123; Path=/; HttpOnly; Secure; SameSite=LaxSet-Cookie: widget_id=public; Path=/; Secure; SameSite=None
JavaScript cannot create an HttpOnly cookie

HttpOnly is a server-set attribute. If you type document.cookie = "session=abc; HttpOnly", you do not get a sealed session cookie. Use a server Set-Cookie header for session tokens, and never store secrets in cookies that JavaScript can read.

That is why authentication cookies are usually set by the server, not by client code: HttpOnly; Secure; SameSite=Lax makes the browser carry the session while keeping page scripts from reading it.

Where you’ll use cookies

SORTER

The deciding question is: does the server need this small value on matching requests? If yes, a cookie may fit. If JavaScript alone needs the value, the next lesson’s localStorage or sessionStorage may be better. If the value is truly secret, keep it out of the browser.

Cookie, localStorage, or neither?
  • Session ID that proves who is signed in
  • Dark mode theme used only after the app loads
  • A secret API key for a paid service
  • Tracking consent choice that the server must respect
  • A large shopping cart with many product details
  • A CSRF signing secret
Try it yourself
0 of 6 correct

Choose the safest storage home for each piece of data.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Common misconceptions

Cookie bugs usually mix up values, attributes, and headers
  • “Writing document.cookie replaces all cookies.” It writes one cookie.
  • “I can read attributes later.” Reads show visible name=value pairs only.
  • “Deleting means setting an empty value.” Empty value is still a cookie; expire it with Max-Age=0 or a past Expires.
  • “Secure hides a cookie from JavaScript.” HttpOnly hides it; Secure controls HTTPS sending.
  • “SameSite replaces CSRF protection.” It helps a lot, but real apps still use careful methods, tokens, and server checks.
  • “Cookies are a good place for secrets.” Only server-set HttpOnly cookies are appropriate for session tokens; never store secret API keys in browser-readable storage.

Practice exercises

5 EXERCISES
Exercise 1 · Warm-upPredict the decoded value

Read the starter code. What exact text does it print?

Starter codePop out in the code editor (opens in a new tab)JavaScript
const raw = "cf_demo_theme=dark; cf_demo_name=Ada%20Lovelace";
const cookies = Object.fromEntries(
  raw.split("; ").map((pair) => pair.split("=").map(decodeURIComponent))
);
console.log(cookies.cf_demo_name);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeWrite the delete string

    Which attribute value belongs in the delete write?

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    document.cookie = "cf_demo_theme=dark; Path=/";
    // Now delete the same cookie.

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeFind the bug: session token in JavaScript

      This app stores a session token from JavaScript. Explain what is wrong and write the safer server header.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      document.cookie = "token=secret.jwt.value; Max-Age=3600; Path=/; Secure";
        Exercise 4 · PracticeSameSite prediction

        A different site submits a POST form to your app. Your session cookie is SameSite=Lax. Is it sent or blocked?

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        // Cross-site POST form with SameSite=Lax
        console.log("blocked");

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeChoose storage for a server-rendered theme

          Your server renders dark mode before the app hydrates. Pick cookie or localStorage for the theme and justify your choice.

            Check your understanding

            7 QUESTIONS
            Cookies quiz · 7 questionsScore: first tries count
            1. Question 1 of 7What does assigning to document.cookie do?

              Choose an answer to see the explanation.

            2. Question 2 of 7What does this print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const raw = "theme=dark; name=Ada%20Lovelace";
              const pairs = raw.split("; ").map((pair) => pair.split("="));
              console.log(decodeURIComponent(pairs[1][1]));

              Choose an answer to see the explanation.

            3. Question 3 of 7If both Expires and Max-Age are present, which one wins?

              Choose an answer to see the explanation.

            4. Question 4 of 7A cross-site POST form submits to your site. Which SameSite value sends the cookie?

              Choose an answer to see the explanation.

            5. Question 5 of 7Which cookie attribute prevents JavaScript from reading the cookie?

              Choose an answer to see the explanation.

            6. Question 6 of 7What readable pair does this simplified cookie read print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const write = "theme=dark; Max-Age=3600; Path=/; SameSite=Lax";
              const readable = write.split(";")[0];
              console.log(readable);

              Choose an answer to see the explanation.

            7. Question 7 of 7When is the Cookie Store API a better fit than document.cookie?

              Choose an answer to see the explanation.

            Key takeaways

            • A cookie is a small name=value record with request-sending rules.
            • document.cookie reads visible cookies as one string and writes one cookie at a time.
            • Max-Age beats Expires; deleting is an expired overwrite with the same name/path/domain.
            • SameSite helps control cross-site sending; None requires Secure.
            • Secure means HTTPS sending; HttpOnly means JavaScript cannot read it.
            • Use Cookie Store API only after feature detection, and keep fallbacks.

            Final definition: a cookie is a tiny browser-stored string that follows matching requests according to attributes set by JavaScript or, more powerfully, by the server.

            Up next: localStorage & sessionStorage.

            CompleteFrontend Clear concepts. Working examples.