HTTP Cookies How to Build and Parse Them Correctly

Опубликовано
HTTP Cookies: How to Build and Parse Them Correctly 1
Реклама · УДАЛИТЬ?

HTTP cookies are everywhere. Every login session, shopping cart, and analytics tool relies on them. Yet most developers copy-paste a Set-Cookie header and move on without understanding what the attributes actually do — or what happens when they get them wrong.

This guide covers cookie anatomy, every meaningful attribute, how to parse cookie strings, and why SameSite is your CSRF defense. If you want to go hands-on right away, try the IO Tools Cookie Parser или Cookie Builder.

What a Cookie Actually Looks Like

When a server wants to set a cookie, it sends a Set-Cookie response header:

Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=86400

The browser stores this and sends it back on subsequent requests as:

Cookie: sessionId=abc123

That is the whole mechanism. The complexity is in those attributes.

Cookie Anatomy: Breaking Down the String

A cookie string follows a consistent format:

name=value; attribute1; attribute2=attributeValue; ...

The name=value pair comes first. Everything after the first semicolon is a directive to the browser — the server never sees these attributes in the Cookie header it receives.

The Security Attributes You Must Get Right

HttpOnly

HttpOnly prevents JavaScript from reading the cookie via document.cookie. This is a direct defense against XSS attacks stealing session tokens.

Set-Cookie: sessionId=abc123; HttpOnly

Any cookie that authenticates a user should have HttpOnly. There is no good reason not to.

Безопасный

Secure means the browser only sends the cookie over HTTPS connections. Without it, the cookie travels in plaintext over HTTP and can be intercepted. In production, session cookies always need Secure. In local development over http://localhost, you can omit it — browsers make an exception for localhost.

SameSite

SameSite controls when the browser includes a cookie in cross-site requests. This is the primary defense against CSRF attacks. Three values:

  • Strict — cookie is never sent on cross-site requests. Most secure, but users clicking a link from an email arrive logged out (the cookie is not sent on that initial navigation).
  • Lax — cookie is sent on top-level navigations (GET requests) from external sites, but not on embedded cross-site requests or cross-site POSTs. This is the browser default for cookies without an explicit SameSite attribute.
  • None — cookie is sent on all cross-site requests. Required for third-party cookies (OAuth flows, embedded widgets). Must be paired with Secure.
# Third-party / cross-site cookie (e.g., OAuth callback)
Set-Cookie: token=xyz; SameSite=None; Secure

If you send SameSite=None без Secure, modern browsers reject the cookie entirely. For most session cookies, use SameSite=Lax — it balances security with a usable login experience.

Scope: Domain and Path

Домен

The Domain attribute specifies which hostnames receive the cookie.

Set-Cookie: user=alice; Domain=example.com

With Domain=example.com, the cookie is sent to example.com and all subdomains (api.example.com, app.example.com). Without a Domain attribute, the cookie is sent only to the exact origin that set it — not to subdomains.

Common misconception: setting Domain=example.com does нет restrict the cookie to just example.com. It broadens scope to include subdomains. Omit the attribute if you want a single-host cookie.

Путь

Path limits which URL paths trigger the cookie being sent.

Set-Cookie: adminToken=xyz; Path=/admin

This cookie only accompanies requests to /admin and paths below it. A request to / или /api would not include it. The default is /, meaning all paths.

Max-Age vs Expires

Both control when a cookie expires. Prefer Max-Age.

  • Expires takes an absolute date in HTTP date format. This is relative to the client’s clock, which you do not control.
  • Max-Age takes a number of seconds from now: Max-Age=86400 for 24 hours. Relative to the server’s intent, not the client’s clock.

When both are present, Max-Age takes precedence. A cookie with neither attribute is a session cookie — it disappears when the browser closes.

Cookie Attribute Reference

AttributeWhat It DoesПо умолчаниюРекомендация
HttpOnlyBlocks JavaScript access to the cookieNot setAlways set for auth cookies
SecureHTTPS-only transmissionNot setAlways set in production
SameSiteControls cross-site sendingLax (modern browsers)Lax for sessions; None + Secure for third-party
DomainSets hostname scopeCurrent host onlyOmit unless cross-subdomain access is needed
PathSets path scope/Leave as / unless isolating admin tokens
Max-AgeSeconds until expirySession cookiePrefer over Expires
ExpiresAbsolute expiry dateSession cookieUse Max-Age instead

Setting Cookies in Code

Node.js (Express)

app.post('/login', (req, res) => {
  // ... verify credentials ...

  res.cookie('sessionId', token, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    maxAge: 86400 * 1000, // milliseconds in Express
    path: '/',
  });

  res.json({ ok: true });
});

Python (FastAPI)

from fastapi import FastAPI, Response

app = FastAPI()

@app.post("/login")
def login(response: Response):
    # ... verify credentials ...

    response.set_cookie(
        key="sessionId",
        value=token,
        httponly=True,
        secure=True,
        samesite="lax",
        max_age=86400,
        path="/",
    )
    return {"ok": True}

Parsing Cookie Headers Manually

The Cookie header the server receives contains only name=value pairs, separated by ; :

Cookie: sessionId=abc123; theme=dark; lang=en

To parse it manually: split on ; (semicolon + space), then split each pair on the first = only. Edge cases worth knowing:

  • Values can contain = (base64 strings commonly do) — always split on the first = only
  • Cookie names are case-sensitive
  • Whitespace around the separator can vary — trim both sides defensively

Rather than write the split logic yourself, use the IO Tools Cookie Parser to decode any Cookie header and inspect each value, or the IO Tools Cookie Builder to construct a valid Set-Cookie header with the right attributes.

Cookies and CSRF

Cross-Site Request Forgery exploits the fact that browsers automatically include cookies on requests to a domain, even when initiated by a different site. A malicious page at evil.com can submit a form to bank.com/transfer, and if the user is logged in, the browser sends their session cookie along with the forged request.

SameSite=Lax defeats most CSRF vectors because cross-site POST requests — the typical attack pattern — do not include the cookie. SameSite=Strict is even more thorough but can affect usability.

CSRF tokens remain valid as defense-in-depth, especially for high-stakes operations and when SameSite=None is required for third-party context. The two defenses complement each other.

Хотите убрать рекламу? Откажитесь от рекламы сегодня

Установите наши расширения

Добавьте инструменты ввода-вывода в свой любимый браузер для мгновенного доступа и более быстрого поиска

в Расширение Chrome в Расширение края в Расширение Firefox в Расширение Opera

Табло результатов прибыло!

Табло результатов — это интересный способ следить за вашими играми, все данные хранятся в вашем браузере. Скоро появятся новые функции!

Реклама · УДАЛИТЬ?
Реклама · УДАЛИТЬ?
Реклама · УДАЛИТЬ?

новости с техническими моментами

Примите участие

Помогите нам продолжать предоставлять ценные бесплатные инструменты

Купи мне кофе
Реклама · УДАЛИТЬ?