AnvilJSON utilities

Anvil › Docs › /v1/cookie/parse

Set-Cookie checker API: why isn't my cookie being set?

When a cookie silently doesn't stick, the reason is almost always one attribute: SameSite=None without Secure, a Domain the site doesn't own, a Secure cookie sent from an http:// page, or a missing Path. Paste the Set-Cookie header your server sends, plus the address that sent it, and this endpoint reads it the way a modern browser does and tells you which rule it broke.

In one line: GET /v1/cookie/parse?header=sid%3Dabc123%3B%20Path%3D/%3B%20HttpOnly%3B%20SameSite%3DNone&url=https%3A//shop.example.co.uk/account/login returns JSON. No key, CORS on, 60 requests a minute.

Parameters

NameTypeWhat it doesDefault
headerstringOne or more Set-Cookie header values, one per line (up to 30 lines, 8 KB). 'Set-Cookie:' in front is fine.—
urlstringThe page or API address that sent the header, so Domain, Secure and the default Path can be checked—
cookiestringInstead of header: a Cookie request header to split up and check for duplicates and size—

Example

Request:

GET https://api.oddlathe.com/v1/cookie/parse?header=sid%3Dabc123%3B%20Path%3D/%3B%20HttpOnly%3B%20SameSite%3DNone&url=https%3A//shop.example.co.uk/account/login

Response (generated by the real code when these docs were last built):

{
 "kind": "set-cookie",
 "count": 1,
 "summary": {
  "rejected": 1
 },
 "cookies": [
  {
   "name": "sid",
   "value": "abc123",
   "size_bytes": 9,
   "verdict": "rejected",
   "expiry": {
    "kind": "session",
    "message": "Session cookie: it goes away when the browser session ends (some browsers restore sessions, so 'close the browser' isn't guaranteed)."
   },
   "scope": {
    "domain": null,
    "host_only": true,
    "path": "/",
    "sent_to": null
   },
   "flags": {
    "secure": false,
    "httponly": true,
    "samesite": "None",
    "effective_samesite": "None",
    "partitioned": false,
    "priority": null
   },
   "attributes": [
    {
     "attribute": "Path",
     "value": "/",
     "meaning": "Send it for every page on the site."
    },
 …

Code examples

curl
curl -G 'https://api.oddlathe.com/v1/cookie/parse' \
  --data-urlencode 'header=sid=abc123; Path=/; HttpOnly; SameSite=None' \
  --data-urlencode 'url=https://shop.example.co.uk/account/login'
JavaScript (browser or Node 18+)
const params = new URLSearchParams({
  header: "sid=abc123; Path=/; HttpOnly; SameSite=None",
  url: "https://shop.example.co.uk/account/login"
});
const res = await fetch(`https://api.oddlathe.com/v1/cookie/parse?${params}`);
if (!res.ok) throw new Error((await res.json()).error.message);
const data = await res.json();
console.log(data);
Python (standard library only)
import json, urllib.parse, urllib.request

params = urllib.parse.urlencode({"header": "sid=abc123; Path=/; HttpOnly; SameSite=None", "url": "https://shop.example.co.uk/account/login"})
url = "https://api.oddlathe.com/v1/cookie/parse?" + params
# Send a User-Agent: the edge network refuses Python's default one.
req = urllib.request.Request(url, headers={"User-Agent": "my-script/1.0"})
with urllib.request.urlopen(req, timeout=10) as r:
    data = json.load(r)
print(data)

When it's useful

  • Debugging login or session cookies that work locally but not in production
  • A CI check that your framework's cookie settings didn't regress (no Secure, no HttpOnly, SameSite missing)
  • Explaining a Set-Cookie line in a code review or support answer
  • Finding duplicate cookie names in a Cookie request header (pass <code>cookie</code> instead of <code>header</code>)

Good to know

  • Send several cookies at once by putting one Set-Cookie value per line (URL-encode the newline as %0A). A leading Set-Cookie: is ignored.
  • verdict is accepted, rejected, deletes (Max-Age 0 or an Expires in the past) or valid when you leave out url. Each item in problems has a code, a severity (error, warn, info) and a message you can show as it is.
  • Codes you may see: samesite_none_needs_secure, secure_from_http, domain_mismatch, public_suffix_domain, host_prefix, secure_prefix, prefix_from_http, partitioned_needs_secure, too_big, default_path, capped_400_days, max_age_wins, lax_by_default, session_without_httponly, session_without_secure, bad_expires, bad_max_age, unknown_attribute, odd_value_chars and duplicate_name.
  • value_hints spots JWTs, URL-encoded and Base64 values and signed session IDs, so you can tell when a cookie carries readable data.
  • It checks whether a cookie is stored. Whether it's later sent on a cross-site request also depends on SameSite and the request type; the Set-Cookie explainer on Tooltern has a would-it-be-sent simulator that runs in your browser.

Reads Set-Cookie headers the way current browsers do (RFC 6265bis): every attribute explained in plain words, a verdict per cookie (accepted, rejected, deletes, or valid when no url is given), and each reason with a severity. Checks SameSite=None without Secure, Secure from http, Domain that doesn't cover the site or is a public suffix (full Public Suffix List), __Host- and __Secure- prefixes, 4096-byte size, Max-Age vs Expires, the 400-day cap, the default-path trap and session cookies missing HttpOnly. Pure text analysis: nothing is fetched or stored.

Errors

Errors are JSON like {"error": {"code": "…", "message": "…"}}. The ones this endpoint can return:

  • bad_param (400): a value is the wrong type or out of range (the message says which)
  • rate_limited (429): over 60 requests a minute; wait for Retry-After seconds

Questions

Why isn't my cookie being set?

Check the browser's network panel for a warning next to the Set-Cookie header, then look for the usual causes: <code>SameSite=None</code> without <code>Secure</code>, <code>Secure</code> from an http page, a <code>Domain</code> the site isn't part of, or a <code>Path</code> that excludes the page you're looking at. This endpoint names the one that applies.

Does Max-Age or Expires win?

Max-Age. When both are present browsers ignore Expires. Max-Age=0 (or any negative number) deletes the cookie.

What does SameSite default to?

Chrome and Edge treat a cookie without SameSite as Lax. Firefox and Safari currently don't, so set it explicitly to get the same behaviour everywhere.

Can a site set a cookie for co.uk or github.io?

No. Those are public suffixes shared by many owners, so browsers refuse a Domain attribute that names one.

Related endpoints

Prefer a page to an API?

Published · OpenAPI 3.1 spec · Limits and privacy