Python’s http.cookies module parses incoming Cookie headers and builds outgoing Set-Cookie headers for HTTP responses. from http.cookies import SimpleCookie, Morsel, CookieError. Create: sc = SimpleCookie() — empty jar. Parse: sc.load("session=abc123; theme=dark") — parses a Cookie or Set-Cookie header string into the jar. Access: sc["session"] → Morsel; sc["session"].value → "abc123" (decoded); sc["session"].coded_value → quoted wire value; sc["session"].key → "session". Set: sc["session"] = "abc123" — creates a new Morsel; sc["session"]["expires"] = "Sat, 01 Jan 2030 00:00:00 GMT"; sc["session"]["path"] = "/", sc["session"]["domain"] = ".example.com", sc["session"]["secure"] = True, sc["session"]["httponly"] = True, sc["session"]["samesite"] = "Lax", sc["session"]["max-age"] = 3600. Output: sc.output() → "Set-Cookie: session=abc123\r\nSet-Cookie: theme=dark" (multi-line); sc.output(header="", sep="\n") for custom formatting; sc["session"].OutputString() → single cookie without Set-Cookie: prefix. Exceptions: CookieError raised for illegal keys or values. Claude Code generates cookie readers, Set-Cookie emitters, session token managers, and test cookie harnesses.
CLAUDE.md for http.cookies
## http.cookies Stack
- Stdlib: from http.cookies import SimpleCookie, CookieError
- Parse: sc = SimpleCookie(); sc.load(cookie_header_string)
- val = sc["name"].value # decoded value
- key = sc["name"].key
- Set: sc["session"] = "tok123"
- sc["session"]["httponly"] = True
- sc["session"]["samesite"] = "Lax"
- sc["session"]["max-age"] = 3600
- Output: sc.output() # multi-line Set-Cookie headers
- sc.output(header="", sep="\n").strip() # values only
http.cookies HTTP Cookie Pipeline
# app/cookiesutil.py — parse, build, sign, validate, expire cookies
from __future__ import annotations
import hashlib
import hmac
import secrets
import time
from dataclasses import dataclass
from datetime import datetime, timezone, timedelta
from http.cookies import SimpleCookie, Morsel, CookieError
# ─────────────────────────────────────────────────────────────────────────────
# 1. Parse helpers
# ─────────────────────────────────────────────────────────────────────────────
def parse_cookie_header(header: str) -> dict[str, str]:
"""
Parse a Cookie: request header string into a {name: value} dict.
Returns empty dict on parse error.
Example:
cookies = parse_cookie_header("session=abc; theme=dark; count=3")
print(cookies["session"]) # 'abc'
"""
sc = SimpleCookie()
try:
sc.load(header)
except CookieError:
return {}
return {key: morsel.value for key, morsel in sc.items()}
def parse_set_cookie_header(header: str) -> dict[str, str | bool]:
"""
Parse a Set-Cookie: response header value (one cookie with attributes).
Returns dict with 'name', 'value', and any set attributes.
Example:
attrs = parse_set_cookie_header(
"session=tok123; Path=/; HttpOnly; SameSite=Lax; Max-Age=3600"
)
"""
sc = SimpleCookie()
try:
sc.load(header)
except CookieError:
return {}
if not sc:
return {}
name = next(iter(sc))
morsel = sc[name]
result: dict[str, str | bool] = {"name": name, "value": morsel.value}
for attr in ("expires", "path", "domain", "comment", "max-age", "samesite"):
v = morsel[attr]
if v:
result[attr] = v
if morsel["secure"]:
result["secure"] = True
if morsel["httponly"]:
result["httponly"] = True
return result
# ─────────────────────────────────────────────────────────────────────────────
# 2. Cookie builder
# ─────────────────────────────────────────────────────────────────────────────
@dataclass
class CookieSpec:
name: str
value: str
max_age: int | None = None # seconds; None = session cookie
path: str = "/"
domain: str = ""
secure: bool = True
httponly: bool = True
samesite: str = "Lax" # "Strict", "Lax", "None"
comment: str = ""
def build_set_cookie(spec: CookieSpec) -> str:
"""
Build a Set-Cookie header value from a CookieSpec.
Returns the full header line including 'Set-Cookie: ' prefix.
Example:
header = build_set_cookie(CookieSpec("session", "tok123", max_age=3600))
print(header)
"""
sc = SimpleCookie()
sc[spec.name] = spec.value
m = sc[spec.name]
m["path"] = spec.path
if spec.domain:
m["domain"] = spec.domain
if spec.max_age is not None:
m["max-age"] = spec.max_age
m["secure"] = spec.secure
m["httponly"] = spec.httponly
m["samesite"] = spec.samesite
if spec.comment:
m["comment"] = spec.comment
return m.OutputString()
def build_cookie_jar(specs: list[CookieSpec]) -> list[str]:
"""
Build a list of Set-Cookie header values from multiple CookieSpecs.
Example:
headers = build_cookie_jar([
CookieSpec("session", "tok123", max_age=3600),
CookieSpec("pref", "dark", max_age=86400*30),
])
for h in headers:
print(f"Set-Cookie: {h}")
"""
return [build_set_cookie(s) for s in specs]
def expire_cookie(name: str, path: str = "/", domain: str = "") -> str:
"""
Build a Set-Cookie header that immediately expires (deletes) a cookie.
Example:
header = expire_cookie("session")
print(f"Set-Cookie: {header}")
"""
return build_set_cookie(CookieSpec(
name=name, value="", max_age=0,
path=path, domain=domain,
secure=False, httponly=False, samesite="Lax",
))
# ─────────────────────────────────────────────────────────────────────────────
# 3. Signed session token
# ─────────────────────────────────────────────────────────────────────────────
def _sign(value: str, secret: str) -> str:
sig = hmac.new(secret.encode(), value.encode(), hashlib.sha256).hexdigest()
return f"{value}.{sig}"
def _verify(signed: str, secret: str) -> str | None:
"""Return the payload if signature is valid, else None."""
if "." not in signed:
return None
payload, _, sig = signed.rpartition(".")
expected = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest()
if hmac.compare_digest(sig, expected):
return payload
return None
def make_session_token(data: str, secret: str) -> str:
"""
Create an HMAC-signed session token string (not base64 — plain hex sig).
Example:
token = make_session_token("user_id=42", secret="supersecret")
verified = verify_session_token(token, secret="supersecret")
"""
return _sign(data, secret)
def verify_session_token(token: str, secret: str) -> str | None:
"""
Verify a signed session token.
Returns the original data string if valid, None if tampered or invalid.
Example:
data = verify_session_token(cookie_value, secret="supersecret")
if data is None:
raise PermissionError("invalid session")
"""
return _verify(token, secret)
def new_session_cookie(
user_id: str | int,
secret: str,
max_age: int = 3600,
domain: str = "",
) -> str:
"""
Generate a new signed session cookie Set-Cookie value.
Example:
header = new_session_cookie(user_id=42, secret="mysecret")
# response.headers["Set-Cookie"] = header
"""
payload = f"uid={user_id};ts={int(time.time())}"
token = make_session_token(payload, secret)
spec = CookieSpec(
name="session",
value=token,
max_age=max_age,
domain=domain,
secure=True,
httponly=True,
samesite="Lax",
)
return build_set_cookie(spec)
# ─────────────────────────────────────────────────────────────────────────────
# 4. Cookie audit
# ─────────────────────────────────────────────────────────────────────────────
@dataclass
class CookieAuditResult:
name: str
warnings: list[str]
@property
def ok(self) -> bool:
return len(self.warnings) == 0
def __str__(self) -> str:
if self.ok:
return f"[OK] {self.name}"
return f"[WARN] {self.name}: {'; '.join(self.warnings)}"
def audit_cookie(name: str, header_value: str) -> CookieAuditResult:
"""
Audit a Set-Cookie header value for common security issues.
Example:
result = audit_cookie("session", "session=tok; Path=/")
print(result)
"""
attrs = parse_set_cookie_header(header_value)
warnings = []
if not attrs.get("httponly"):
warnings.append("missing HttpOnly (accessible via JS)")
if not attrs.get("secure"):
warnings.append("missing Secure (sent over HTTP)")
samesite = str(attrs.get("samesite", "")).lower()
if samesite not in ("strict", "lax"):
warnings.append(f"SameSite={samesite!r} (prefer Strict or Lax)")
if not attrs.get("max-age") and not attrs.get("expires"):
warnings.append("session cookie (no expiry)")
return CookieAuditResult(name=name, warnings=warnings)
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
print("=== http.cookies demo ===")
# ── parse_cookie_header ───────────────────────────────────────────────────
print("\n--- parse_cookie_header ---")
cookies = parse_cookie_header("session=abc123; theme=dark; count=3")
for k, v in cookies.items():
print(f" {k} = {v!r}")
# ── build_set_cookie ───────────────────────────────────────────────────────
print("\n--- build_set_cookie ---")
spec = CookieSpec(
name="session", value="tok_xyz789",
max_age=3600, path="/", domain=".example.com",
secure=True, httponly=True, samesite="Strict",
)
header = build_set_cookie(spec)
print(f" Set-Cookie: {header}")
# ── build_cookie_jar ──────────────────────────────────────────────────────
print("\n--- build_cookie_jar ---")
headers = build_cookie_jar([
CookieSpec("session", "tok_abc", max_age=3600),
CookieSpec("pref", "dark_mode", max_age=86400 * 30, httponly=False),
])
for h in headers:
print(f" Set-Cookie: {h}")
# ── expire_cookie ─────────────────────────────────────────────────────────
print("\n--- expire_cookie ---")
print(f" Set-Cookie: {expire_cookie('session')}")
# ── signed session token ───────────────────────────────────────────────────
print("\n--- signed session ---")
secret = secrets.token_hex(16)
cookie_hdr = new_session_cookie(user_id=42, secret=secret)
print(f" Set-Cookie: {cookie_hdr[:80]}...")
cookies2 = parse_cookie_header(f"session={cookie_hdr.split('=', 1)[1].split(';')[0]}")
raw_token = cookies2.get("session", "")
data = verify_session_token(raw_token, secret)
print(f" verified data: {data}")
tampered = raw_token + "x"
print(f" tampered: {verify_session_token(tampered, secret)}")
# ── audit_cookie ───────────────────────────────────────────────────────────
print("\n--- audit_cookie ---")
tests = [
("good", build_set_cookie(CookieSpec("good", "v", max_age=3600))),
("no-flags","no_flags=v; Path=/"),
("no-expiry", build_set_cookie(CookieSpec("noexp", "v", max_age=None))),
]
for name, hdr in tests:
result = audit_cookie(name, hdr)
print(f" {result}")
print("\n=== done ===")
For the http.cookiejar alternative — http.cookiejar.CookieJar and urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar)) handle automatic cookie sending and storage in client-side HTTP sessions, with MozillaCookieJar and LWPCookieJar for file persistence — use http.cookiejar when you are writing an HTTP client that needs to automatically manage cookies across redirects and requests (like a browser session); use http.cookies when you are writing an HTTP server or middleware that needs to parse incoming Cookie: headers and generate outgoing Set-Cookie: headers. For the itsdangerous (PyPI) alternative — itsdangerous.URLSafeTimedSerializer(secret).dumps(data) and .loads(token, max_age=3600) provide tamper-proof, optionally timestamped signed cookies with structured data serialization — use itsdangerous in production web apps that need signed session cookies with expiry enforcement and structured payload; use http.cookies for zero-dependency header parsing and simple Set-Cookie generation in lightweight or stdlib-only environments. The Claude Skills 360 bundle includes http.cookies skill sets covering parse_cookie_header()/parse_set_cookie_header() parsers, CookieSpec with build_set_cookie()/build_cookie_jar()/expire_cookie() builders, make_session_token()/verify_session_token()/new_session_cookie() HMAC signing, and CookieAuditResult with audit_cookie() security checker. Start with the free tier to try HTTP cookie patterns and http.cookies pipeline code generation.