Skip to main content

Set-Cookie Parser & Cookie Delivery API

REAL DATA

Parse Set-Cookie and test delivery: attribute rules, __Host-/__Secure- prefixes, SameSite+Secure, Max-Age vs Expires precedence, and domain/path matching.

Authoritative reference data or standards computation

Base URL
/api/cookies
Capabilities
2 routes
Last updated
July 29, 2026
Data source

GET /api/cookies/parse

Normalizes the header into the fields a user agent stores and returns a per-rule verdict trace. A string that is not a set-cookie-string at all (no '=', or an empty name) is a 400; a cookie that parses but would be refused returns 200 with accepted=false.

Live requestRuns against the public API
No key required
GET/api/cookies/parse?setCookie=__Host-sid%3Da1b2c3%3B+Path%3D%2F%3B+Secure%3B+HttpOnly%3B+SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard

Request parameters

The Set-Cookie field value, without the field name (a leading 'Set-Cookie:' is stripped for you). Do not paste a real session cookie — use a placeholder value.

The URL whose response sent the cookie. Its host drives host-only and domain-match, its path drives the §5.1.4 default-path, and its scheme decides whether Secure is allowed.

Evaluation instant (UTC). Defaults to the current time. On /match this is both the moment the cookie was received and the moment of the request, so a positive Max-Age is never expired — model an aged-out cookie with Expires.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/cookies/parse?setCookie=__Host-sid%3Da1b2c3%3B%20Path%3D%2F%3B%20Secure%3B%20HttpOnly%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard"
const res = await fetch("https://randomapi.dev/api/cookies/parse?setCookie=__Host-sid%3Da1b2c3%3B%20Path%3D%2F%3B%20Secure%3B%20HttpOnly%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/cookies/parse?setCookie=__Host-sid%3Da1b2c3%3B%20Path%3D%2F%3B%20Secure%3B%20HttpOnly%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/cookies/parse?setCookie=__Host-sid%3Da1b2c3%3B%20Path%3D%2F%3B%20Secure%3B%20HttpOnly%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 3
setCookie string required

The Set-Cookie field value, without the field name (a leading 'Set-Cookie:' is stripped for you). Do not paste a real session cookie — use a placeholder value.

allowed: ≤ 4096
example: setCookie=__Host-sid=a1b2c3; Path=/; Secure; HttpOnly; SameSite=Lax
originUrl string

The URL whose response sent the cookie. Its host drives host-only and domain-match, its path drives the §5.1.4 default-path, and its scheme decides whether Secure is allowed.

default: https://example.com/
allowed: ≤ 2048
example: originUrl=https://app.example.com/dashboard/settings
at date

Evaluation instant (UTC). Defaults to the current time. On /match this is both the moment the cookie was received and the moment of the request, so a positive Max-Age is never expired — model an aged-out cookie with Expires.

example: at=2026-01-15T09:30:00Z
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=name,value
exclude list

Return all fields except these (comma-separated).

example: exclude=warnings
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 16
name string

cookie-name after RFC 6265 §5.2 WSP trimming.

example: __Host-sid

value string

cookie-value after WSP trimming; surrounding double quotes are NOT removed.

example: a1b2c3

attributes object

Parsed attributes as sent, before any lifetime limit: expires (ISO 8601 or null), maxAge (delta-seconds or null), domain (lower-cased, leading dot removed, otherwise unvalidated), path (raw value or null), secure, httpOnly, sameSite (raw token or null).

example: {"expires":null,"maxAge":3600,"domain":null,"path":"/","secure":true,"httpOnly":true,"sameSite":"Lax"}

effectiveExpiry string (ISO 8601) nullable

Expiry a user agent would store: Max-Age wins over Expires (RFC 6265 §5.3), then the rfc6265bis §5.5 400-day lifetime limit is applied. Null for a session cookie.

example: 2026-01-15T10:30:00.000Z

expirySource string

Which attribute produced effectiveExpiry: Max-Age, Expires or session.

example: Max-Age

hostOnly boolean

True when there is no usable Domain attribute, locking the cookie to the origin host.

example: true

cookieDomain string

Domain a user agent would store: the Domain attribute, or the canonicalized origin host when host-only.

example: app.example.com

defaultPath string

RFC 6265 §5.1.4 default-path of the origin URL — everything up to but not including the right-most '/', or '/'. This is what a cookie gets when Path is omitted.

example: /dashboard

cookiePath string

Path a user agent would store: a Path attribute starting with '/', otherwise defaultPath.

example: /

prefix string

Detected name prefix: none, __Host- or __Secure-.

example: __Host-

prefixVerdict string

pass, fail or not-applicable for the detected prefix's requirements.

example: pass

prefixFailure string nullable

The prefix requirement(s) that failed, or null when the prefix passes or is absent.

example: null

accepted boolean

Whether a user agent applying every rule below would store this cookie, assuming the rules reported as 'not-checked' pass. When that assumption is what makes this true, a warning names the rule.

example: true

rules object[]

Ordered storage rules, each with rule, verdict (pass | fail | not-applicable | not-checked), detail and specSource ('RFC 6265' or 'rfc6265bis draft'). Every rule is evaluated, so all failures are visible at once.

example: [{"rule":"__Host- prefix requires Secure, no Domain attribute and an explicit Path=/","verdict":"fail","detail":"__Host- cookies must not carry a Domain attribute. The cookie is ignored entirely.","specSource":"rfc6265bis draft"}]

rejectedAttributes object[]

Attributes that were parsed and then discarded, each with attribute, value, reason and specSource.

example: [{"attribute":"Expires","value":"tomorrow","reason":"The value did not parse as a cookie-date under the RFC 6265 §5.1.1 algorithm, so the attribute is ignored and the cookie becomes a session cookie unless Max-Age is present.","specSource":"RFC 6265"}]

warnings string[]

Advisory notes about this cookie — spec footguns, browser-specific behaviour and checks this API does not perform.

example: ["'Domain=example.com' is not host-only: it also sends the cookie to every subdomain of example.com. Omit the Domain attribute if you want a host-only cookie."]

Documented examples

Build-generated requests and complete responses
7
A valid __Host- session cookie
GET /api/cookies/parse?setCookie=__Host-sid%3Da1b2c3%3B%20Path%3D%2F%3B%20Secure%3B%20HttpOnly%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard
{
  "data": {
    "name": "__Host-sid",
    "value": "a1b2c3",
    "attributes": {
      "expires": null,
      "maxAge": null,
      "domain": null,
      "path": "/",
      "secure": true,
      "httpOnly": true,
      "sameSite": "Lax"
    },
    "effectiveExpiry": null,
    "expirySource": "session",
    "hostOnly": true,
    "cookieDomain": "app.example.com",
    "defaultPath": "/",
    "cookiePath": "/",
    "prefix": "__Host-",
    "prefixVerdict": "pass",
    "prefixFailure": null,
    "accepted": true,
    "rules": [
      {
        "rule": "set-cookie-string contains no control characters",
        "verdict": "pass",
        "detail": "No control characters appear anywhere in the header.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "cookie-name and cookie-value are at most 4096 octets",
        "verdict": "pass",
        "detail": "The name and value total 16 octets.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "Domain attribute is not a public suffix",
        "verdict": "not-applicable",
        "detail": "There is no Domain attribute, so the cookie is host-only and the public-suffix rule cannot apply.",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
__Host- with a Domain attribute fails
GET /api/cookies/parse?setCookie=__Host-sid%3Da1b2c3%3B%20Path%3D%2F%3B%20Domain%3Dexample.com%3B%20Secure&originUrl=https%3A%2F%2Fapp.example.com%2F
{
  "data": {
    "name": "__Host-sid",
    "value": "a1b2c3",
    "attributes": {
      "expires": null,
      "maxAge": null,
      "domain": "example.com",
      "path": "/",
      "secure": true,
      "httpOnly": false,
      "sameSite": null
    },
    "effectiveExpiry": null,
    "expirySource": "session",
    "hostOnly": false,
    "cookieDomain": "example.com",
    "defaultPath": "/",
    "cookiePath": "/",
    "prefix": "__Host-",
    "prefixVerdict": "fail",
    "prefixFailure": "__Host- cookies must not carry a Domain attribute",
    "accepted": false,
    "rules": [
      {
        "rule": "set-cookie-string contains no control characters",
        "verdict": "pass",
        "detail": "No control characters appear anywhere in the header.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "cookie-name and cookie-value are at most 4096 octets",
        "verdict": "pass",
        "detail": "The name and value total 16 octets.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "Domain attribute is not a public suffix",
        "verdict": "not-checked",
        "detail": "This API deliberately does not consult the Public Suffix List, so 'Domain=example.com' is not tested for being too broad. A real browser rejects Domain values such as 'com' or 'co.uk'. Check the value against publicsuffix.org yourself.",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Default path for an origin of /a/b/c
GET /api/cookies/parse?setCookie=sid%3Da1b2c3&originUrl=https%3A%2F%2Fexample.com%2Fa%2Fb%2Fc
{
  "data": {
    "name": "sid",
    "value": "a1b2c3",
    "attributes": {
      "expires": null,
      "maxAge": null,
      "domain": null,
      "path": null,
      "secure": false,
      "httpOnly": false,
      "sameSite": null
    },
    "effectiveExpiry": null,
    "expirySource": "session",
    "hostOnly": true,
    "cookieDomain": "example.com",
    "defaultPath": "/a/b",
    "cookiePath": "/a/b",
    "prefix": "none",
    "prefixVerdict": "not-applicable",
    "prefixFailure": null,
    "accepted": true,
    "rules": [
      {
        "rule": "set-cookie-string contains no control characters",
        "verdict": "pass",
        "detail": "No control characters appear anywhere in the header.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "cookie-name and cookie-value are at most 4096 octets",
        "verdict": "pass",
        "detail": "The name and value total 9 octets.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "Domain attribute is not a public suffix",
        "verdict": "not-applicable",
        "detail": "There is no Domain attribute, so the cookie is host-only and the public-suffix rule cannot apply.",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Max-Age=0 beats a future Expires
GET /api/cookies/parse?setCookie=sid%3Da1b2c3%3B%20Max-Age%3D0%3B%20Expires%3DFri%2C%2031%20Dec%202027%2023%3A59%3A59%20GMT&at=2026-01-15T09%3A30%3A00Z
{
  "data": {
    "name": "sid",
    "value": "a1b2c3",
    "attributes": {
      "expires": "2027-12-31T23:59:59.000Z",
      "maxAge": 0,
      "domain": null,
      "path": null,
      "secure": false,
      "httpOnly": false,
      "sameSite": null
    },
    "effectiveExpiry": "1601-01-01T00:00:00.000Z",
    "expirySource": "Max-Age",
    "hostOnly": true,
    "cookieDomain": "example.com",
    "defaultPath": "/",
    "cookiePath": "/",
    "prefix": "none",
    "prefixVerdict": "not-applicable",
    "prefixFailure": null,
    "accepted": true,
    "rules": [
      {
        "rule": "set-cookie-string contains no control characters",
        "verdict": "pass",
        "detail": "No control characters appear anywhere in the header.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "cookie-name and cookie-value are at most 4096 octets",
        "verdict": "pass",
        "detail": "The name and value total 9 octets.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "Domain attribute is not a public suffix",
        "verdict": "not-applicable",
        "detail": "There is no Domain attribute, so the cookie is host-only and the public-suffix rule cannot apply.",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
SameSite=None without Secure is rejected
GET /api/cookies/parse?setCookie=sid%3Da1b2c3%3B%20SameSite%3DNone&originUrl=https%3A%2F%2Fexample.com%2F
{
  "data": {
    "name": "sid",
    "value": "a1b2c3",
    "attributes": {
      "expires": null,
      "maxAge": null,
      "domain": null,
      "path": null,
      "secure": false,
      "httpOnly": false,
      "sameSite": "None"
    },
    "effectiveExpiry": null,
    "expirySource": "session",
    "hostOnly": true,
    "cookieDomain": "example.com",
    "defaultPath": "/",
    "cookiePath": "/",
    "prefix": "none",
    "prefixVerdict": "not-applicable",
    "prefixFailure": null,
    "accepted": false,
    "rules": [
      {
        "rule": "set-cookie-string contains no control characters",
        "verdict": "pass",
        "detail": "No control characters appear anywhere in the header.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "cookie-name and cookie-value are at most 4096 octets",
        "verdict": "pass",
        "detail": "The name and value total 9 octets.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "Domain attribute is not a public suffix",
        "verdict": "not-applicable",
        "detail": "There is no Domain attribute, so the cookie is host-only and the public-suffix rule cannot apply.",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
A Domain with a port kills the cookie
GET /api/cookies/parse?setCookie=sid%3Da1b2c3%3B%20Domain%3Dexample.com%3A8080&originUrl=https%3A%2F%2Fapp.example.com%2F
{
  "data": {
    "name": "sid",
    "value": "a1b2c3",
    "attributes": {
      "expires": null,
      "maxAge": null,
      "domain": "example.com:8080",
      "path": null,
      "secure": false,
      "httpOnly": false,
      "sameSite": null
    },
    "effectiveExpiry": null,
    "expirySource": "session",
    "hostOnly": false,
    "cookieDomain": "example.com:8080",
    "defaultPath": "/",
    "cookiePath": "/",
    "prefix": "none",
    "prefixVerdict": "not-applicable",
    "prefixFailure": null,
    "accepted": false,
    "rules": [
      {
        "rule": "set-cookie-string contains no control characters",
        "verdict": "pass",
        "detail": "No control characters appear anywhere in the header.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "cookie-name and cookie-value are at most 4096 octets",
        "verdict": "pass",
        "detail": "The name and value total 9 octets.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "Domain attribute is not a public suffix",
        "verdict": "not-checked",
        "detail": "This API deliberately does not consult the Public Suffix List, so 'Domain=example.com:8080' is not tested for being too broad. A real browser rejects Domain values such as 'com' or 'co.uk'. Check the value against publicsuffix.org yourself.",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
A two-year Max-Age is cut to 400 days
GET /api/cookies/parse?setCookie=sid%3Da1b2c3%3B%20Max-Age%3D63072000&at=2026-01-15T09%3A30%3A00Z
{
  "data": {
    "name": "sid",
    "value": "a1b2c3",
    "attributes": {
      "expires": null,
      "maxAge": 63072000,
      "domain": null,
      "path": null,
      "secure": false,
      "httpOnly": false,
      "sameSite": null
    },
    "effectiveExpiry": "2027-02-19T09:30:00.000Z",
    "expirySource": "Max-Age",
    "hostOnly": true,
    "cookieDomain": "example.com",
    "defaultPath": "/",
    "cookiePath": "/",
    "prefix": "none",
    "prefixVerdict": "not-applicable",
    "prefixFailure": null,
    "accepted": true,
    "rules": [
      {
        "rule": "set-cookie-string contains no control characters",
        "verdict": "pass",
        "detail": "No control characters appear anywhere in the header.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "cookie-name and cookie-value are at most 4096 octets",
        "verdict": "pass",
        "detail": "The name and value total 9 octets.",
        "specSource": "rfc6265bis draft"
      },
      {
        "rule": "Domain attribute is not a public suffix",
        "verdict": "not-applicable",
        "detail": "There is no Domain attribute, so the cookie is host-only and the public-suffix rule cannot apply.",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

GET /api/cookies/match

Applies the storage rules first (a cookie that was never stored can never be sent), then the retrieval rules: expiry, domain-match, path-match, Secure and SameSite. Only failing storage rules are listed; use /parse for the full storage trace.

Live requestRuns against the public API
No key required
GET/api/cookies/match?setCookie=sid%3Da1b2c3%3B+Path%3D%2Fdashboard%3B+Secure%3B+HttpOnly%3B+SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings&requestUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings%2Fprofile

Request parameters

The Set-Cookie field value, without the field name (a leading 'Set-Cookie:' is stripped for you). Do not paste a real session cookie — use a placeholder value.

The URL that set the cookie. Drives host-only, domain-match and the §5.1.4 default-path.

The URL being requested. Its host is tested against the cookie's domain and its path against the cookie's path.

Evaluation instant (UTC). Defaults to the current time. On /match this is both the moment the cookie was received and the moment of the request, so a positive Max-Age is never expired — model an aged-out cookie with Expires.

Whether the request is same-site or cross-site relative to the cookie's site. Drives the SameSite decision.

Whether the request connection counts as secure for the Secure attribute. This parameter decides the check, not the requestUrl scheme, so you can model http://localhost; a mismatch with the scheme is warned about.

Whether the cross-site request is a top-level navigation (a link click) rather than a subresource. Only affects Lax and Default enforcement; a safe request method is assumed.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/cookies/match?setCookie=sid%3Da1b2c3%3B%20Path%3D%2Fdashboard%3B%20Secure%3B%20HttpOnly%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings&requestUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings%2Fprofile"
const res = await fetch("https://randomapi.dev/api/cookies/match?setCookie=sid%3Da1b2c3%3B%20Path%3D%2Fdashboard%3B%20Secure%3B%20HttpOnly%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings&requestUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings%2Fprofile");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/cookies/match?setCookie=sid%3Da1b2c3%3B%20Path%3D%2Fdashboard%3B%20Secure%3B%20HttpOnly%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings&requestUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings%2Fprofile").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/cookies/match?setCookie=sid%3Da1b2c3%3B%20Path%3D%2Fdashboard%3B%20Secure%3B%20HttpOnly%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings&requestUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings%2Fprofile"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 7
setCookie string required

The Set-Cookie field value, without the field name (a leading 'Set-Cookie:' is stripped for you). Do not paste a real session cookie — use a placeholder value.

allowed: ≤ 4096
example: setCookie=sid=a1b2c3; Path=/dashboard; Secure; HttpOnly; SameSite=Lax
originUrl string required

The URL that set the cookie. Drives host-only, domain-match and the §5.1.4 default-path.

allowed: ≤ 2048
example: originUrl=https://app.example.com/dashboard/settings
requestUrl string required

The URL being requested. Its host is tested against the cookie's domain and its path against the cookie's path.

allowed: ≤ 2048
example: requestUrl=https://app.example.com/dashboard/settings/profile
at date

Evaluation instant (UTC). Defaults to the current time. On /match this is both the moment the cookie was received and the moment of the request, so a positive Max-Age is never expired — model an aged-out cookie with Expires.

example: at=2026-01-15T09:30:00Z
sameSiteContext enum

Whether the request is same-site or cross-site relative to the cookie's site. Drives the SameSite decision.

default: same-site
allowed: same-site | cross-site
example: sameSiteContext=cross-site
secureContext boolean

Whether the request connection counts as secure for the Secure attribute. This parameter decides the check, not the requestUrl scheme, so you can model http://localhost; a mismatch with the scheme is warned about.

default: true
example: secureContext=false
isTopLevelNavigation boolean

Whether the cross-site request is a top-level navigation (a link click) rather than a subresource. Only affects Lax and Default enforcement; a safe request method is assumed.

default: false
example: isTopLevelNavigation=true
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=wouldBeSent,stored
exclude list

Return all fields except these (comma-separated).

example: exclude=warnings
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 14
wouldBeSent boolean

Whether a user agent would include this cookie in the request's Cookie header, assuming the set-time rules reported as 'not-checked' pass (a warning names them when that assumption is load-bearing).

example: true

stored boolean

Whether the cookie was accepted at set time, assuming the rules reported as 'not-checked' pass; a cookie that was never stored can never be sent.

example: true

decidingRule string nullable

First rule that excluded the cookie, or null when it is sent.

example: null

name string

cookie-name being tested.

example: sid

cookieDomain string

Domain a user agent would have stored for this cookie.

example: app.example.com

cookiePath string

Path a user agent would have stored for this cookie.

example: /dashboard

hostOnly boolean

True when the cookie is locked to one host (no Domain attribute).

example: true

sameSite string

Effective same-site enforcement: Strict, Lax, None or Default (no/unrecognized attribute).

example: Lax

effectiveExpiry string (ISO 8601) nullable

Expiry used for the expiry check, after the rfc6265bis §5.5 400-day lifetime limit; null for a session cookie.

example: null

requestHost string

Canonicalized host of the request URL.

example: app.example.com

requestPath string

Path of the request URL used for path-match.

example: /dashboard/settings/profile

cookieHeader string nullable

The Cookie header field value this cookie contributes, or null when it is not sent.

example: sid=a1b2c3

reasons object[]

Every failing storage rule followed by all retrieval rules — expiry, domain-match, path-match, Secure, SameSite and HttpOnly — each with rule, verdict, detail and specSource.

example: [{"rule":"SameSite enforcement for this request context","verdict":"fail","detail":"'Lax' enforcement withholds the cookie from cross-site subresource requests and non-top-level navigations. Set isTopLevelNavigation=true to model a link click.","specSource":"rfc6265bis draft"}]

warnings string[]

Advisory notes about the cookie and the modelled request context.

example: []

Documented examples

Build-generated requests and complete responses
5
Same-site request below the cookie path
GET /api/cookies/match?setCookie=sid%3Da1b2c3%3B%20Path%3D%2Fdashboard%3B%20Secure%3B%20HttpOnly%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings&requestUrl=https%3A%2F%2Fapp.example.com%2Fdashboard%2Fsettings%2Fprofile
{
  "data": {
    "wouldBeSent": true,
    "stored": true,
    "decidingRule": null,
    "name": "sid",
    "cookieDomain": "app.example.com",
    "cookiePath": "/dashboard",
    "hostOnly": true,
    "sameSite": "Lax",
    "effectiveExpiry": null,
    "requestHost": "app.example.com",
    "requestPath": "/dashboard/settings/profile",
    "cookieHeader": "sid=a1b2c3",
    "reasons": [
      {
        "rule": "Cookie has not expired",
        "verdict": "not-applicable",
        "detail": "This is a session cookie: no Max-Age and no usable Expires, so it never expires on its own.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Request host matches the cookie's domain",
        "verdict": "pass",
        "detail": "The cookie is host-only, so the request host 'app.example.com' must equal 'app.example.com' exactly — it does.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Request path path-matches the cookie's path",
        "verdict": "pass",
        "detail": "The request path '/dashboard/settings/profile' path-matches the cookie path '/dashboard'. A cookie path matches itself, anything below it after a '/', and nothing else — '/foo' never matches '/foobar'.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Secure cookies are only sent over a secure connection",
        "verdict": "pass",
        "detail": "The cookie is Secure and the modelled request connection is secure.",
        "specSource": "RFC 6265"
      },
      {
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Cross-site subresource drops a Lax cookie
GET /api/cookies/match?setCookie=sid%3Da1b2c3%3B%20Secure%3B%20SameSite%3DLax&originUrl=https%3A%2F%2Fapp.example.com%2F&requestUrl=https%3A%2F%2Fapp.example.com%2Fapi%2Fme&sameSiteContext=cross-site
{
  "data": {
    "wouldBeSent": false,
    "stored": true,
    "decidingRule": "SameSite enforcement for this request context",
    "name": "sid",
    "cookieDomain": "app.example.com",
    "cookiePath": "/",
    "hostOnly": true,
    "sameSite": "Lax",
    "effectiveExpiry": null,
    "requestHost": "app.example.com",
    "requestPath": "/api/me",
    "cookieHeader": null,
    "reasons": [
      {
        "rule": "Cookie has not expired",
        "verdict": "not-applicable",
        "detail": "This is a session cookie: no Max-Age and no usable Expires, so it never expires on its own.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Request host matches the cookie's domain",
        "verdict": "pass",
        "detail": "The cookie is host-only, so the request host 'app.example.com' must equal 'app.example.com' exactly — it does.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Request path path-matches the cookie's path",
        "verdict": "pass",
        "detail": "The request path '/api/me' path-matches the cookie path '/'. A cookie path matches itself, anything below it after a '/', and nothing else — '/foo' never matches '/foobar'.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Secure cookies are only sent over a secure connection",
        "verdict": "pass",
        "detail": "The cookie is Secure and the modelled request connection is secure.",
        "specSource": "RFC 6265"
      },
      {
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Path /foo does not match /foobar
GET /api/cookies/match?setCookie=sid%3Da1b2c3%3B%20Path%3D%2Ffoo&originUrl=https%3A%2F%2Fexample.com%2F&requestUrl=https%3A%2F%2Fexample.com%2Ffoobar
{
  "data": {
    "wouldBeSent": false,
    "stored": true,
    "decidingRule": "Request path path-matches the cookie's path",
    "name": "sid",
    "cookieDomain": "example.com",
    "cookiePath": "/foo",
    "hostOnly": true,
    "sameSite": "Default",
    "effectiveExpiry": null,
    "requestHost": "example.com",
    "requestPath": "/foobar",
    "cookieHeader": null,
    "reasons": [
      {
        "rule": "Cookie has not expired",
        "verdict": "not-applicable",
        "detail": "This is a session cookie: no Max-Age and no usable Expires, so it never expires on its own.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Request host matches the cookie's domain",
        "verdict": "pass",
        "detail": "The cookie is host-only, so the request host 'example.com' must equal 'example.com' exactly — it does.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Request path path-matches the cookie's path",
        "verdict": "fail",
        "detail": "The request path '/foobar' does not path-match the cookie path '/foo'. A cookie path matches itself, anything below it after a '/', and nothing else — '/foo' never matches '/foobar'.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Secure cookies are only sent over a secure connection",
        "verdict": "not-applicable",
        "detail": "The cookie has no Secure attribute, so it is sent over insecure connections too.",
        "specSource": "RFC 6265"
      },
      {
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Expired cookie is never sent
GET /api/cookies/match?setCookie=sid%3Da1b2c3%3B%20Expires%3DWed%2C%2001%20Jan%202020%2000%3A00%3A00%20GMT&originUrl=https%3A%2F%2Fexample.com%2F&requestUrl=https%3A%2F%2Fexample.com%2F&at=2026-01-15T09%3A30%3A00Z
{
  "data": {
    "wouldBeSent": false,
    "stored": true,
    "decidingRule": "Cookie has not expired",
    "name": "sid",
    "cookieDomain": "example.com",
    "cookiePath": "/",
    "hostOnly": true,
    "sameSite": "Default",
    "effectiveExpiry": "2020-01-01T00:00:00.000Z",
    "requestHost": "example.com",
    "requestPath": "/",
    "cookieHeader": null,
    "reasons": [
      {
        "rule": "Cookie has not expired",
        "verdict": "fail",
        "detail": "The Expires expiry 2020-01-01T00:00:00.000Z is at or before the evaluation instant 2026-01-15T09:30:00.000Z, so the user agent has already removed the cookie.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Request host matches the cookie's domain",
        "verdict": "pass",
        "detail": "The cookie is host-only, so the request host 'example.com' must equal 'example.com' exactly — it does.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Request path path-matches the cookie's path",
        "verdict": "pass",
        "detail": "The request path '/' path-matches the cookie path '/'. A cookie path matches itself, anything below it after a '/', and nothing else — '/foo' never matches '/foobar'.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Secure cookies are only sent over a secure connection",
        "verdict": "not-applicable",
        "detail": "The cookie has no Secure attribute, so it is sent over insecure connections too.",
        "specSource": "RFC 6265"
      },
      {
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Subdomain cookie reaching a sibling host
GET /api/cookies/match?setCookie=sid%3Da1b2c3%3B%20Domain%3Dexample.com%3B%20Secure&originUrl=https%3A%2F%2Fapp.example.com%2F&requestUrl=https%3A%2F%2Fapi.example.com%2Fv1%2Fme
{
  "data": {
    "wouldBeSent": true,
    "stored": true,
    "decidingRule": null,
    "name": "sid",
    "cookieDomain": "example.com",
    "cookiePath": "/",
    "hostOnly": false,
    "sameSite": "Default",
    "effectiveExpiry": null,
    "requestHost": "api.example.com",
    "requestPath": "/v1/me",
    "cookieHeader": "sid=a1b2c3",
    "reasons": [
      {
        "rule": "Cookie has not expired",
        "verdict": "not-applicable",
        "detail": "This is a session cookie: no Max-Age and no usable Expires, so it never expires on its own.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Request host matches the cookie's domain",
        "verdict": "pass",
        "detail": "The request host 'api.example.com' domain-matches the cookie domain 'example.com'. Domain-match needs an exact match or a '.' immediately before the suffix.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Request path path-matches the cookie's path",
        "verdict": "pass",
        "detail": "The request path '/v1/me' path-matches the cookie path '/'. A cookie path matches itself, anything below it after a '/', and nothing else — '/foo' never matches '/foobar'.",
        "specSource": "RFC 6265"
      },
      {
        "rule": "Secure cookies are only sent over a secure connection",
        "verdict": "pass",
        "detail": "The cookie is Secure and the modelled request connection is secure.",
        "specSource": "RFC 6265"
      },
      {
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

About this API

Coverage & behavior

Two decision procedures for the question every backend engineer eventually asks: why isn't my cookie being set — and why isn't it coming back?

/parse runs a Set-Cookie field value through RFC 6265 §5.2 and reports what a user agent would actually store: the trimmed name and value, every attribute, the effectiveExpiry (Max-Age wins whenever both Max-Age and Expires are present, per §5.3 step 3), the hostOnly flag, the default-path derived from the origin URL, the detected name prefix, every attribute that was parsed and then discarded, and a rule-by-rule verdict trace. /match then answers whether that cookie would be attached to a specific request URL in a specific context, naming the rule that decided it.

Default-path is the classic bug. RFC 6265 §5.1.4 derives it from the URL that set the cookie, not the one requesting it, and it is everything up to but not including the right-most /. A cookie set from https://example.com/a/b/c with no Path attribute gets the path /a/b — not /a/b/c, and not /.

Expires uses the cookie-date algorithm, not an HTTP-date parser. §5.1.1 tokenizes the value and takes the first token matching each of time, day-of-month, month and year, in that order. That accepts the three HTTP-date forms (IMF-fixdate, RFC 850 and asctime) and much more: any token ordering, unpadded fields and two-digit years (70–99 ⇒ 1900s, 00–69 ⇒ 2000s). It never validates the weekday, so a wrong weekday still parses, and it ignores the time zone entirely — a value ending in PST is still read as UTC. Dates that do not exist, such as 31 February, fail to parse (§5.1.1 step 6) and the attribute is dropped. Expiry instants are reported in the range 1601-01-01 to 9999-12-31; Max-Age values of zero or less report the earliest of those, which is the standard deletion idiom.

Your cookie does not last two years. rfc6265bis §5.5 makes capping a cookie's lifetime a MUST and recommends 400 days (34,560,000 seconds) as the limit, with anything longer reduced to it. This API applies the recommended value, so effectiveExpiry cuts a longer Max-Age or Expires back to 400 days after the evaluation instant and warns when it does; a user agent is allowed to choose a shorter limit than that, so treat 400 days as the ceiling rather than a guarantee. attributes.maxAge and attributes.expires still report exactly what you sent, so you can see both numbers. RFC 6265 has no such cap — this is one of the rules the published RFC does not contain.

A malformed Domain does not become host-only. Neither §5.2.3 nor the draft validates the Domain attribute-value: it is lower-cased, one leading . is stripped, and that is all. Domain=example.com:8080 is therefore stored as written, fails to domain-match the origin host, and §5.3 step 6 discards the whole cookie — it does not quietly fall back to a host-only cookie that works. Only an empty value (or a bare .) leaves the domain-attribute empty and makes the cookie host-only. Internationalized values are converted to A-labels per §5.1.2 (Domain=BÜCHER.examplexn--bcher-kva.example); nothing else about the value is rewritten, so percent-escapes are not decoded and 168.0.1 is not expanded into an IP address.

What comes from a draft, and what does not. Cookie prefixes (__Host-, __Secure-), the whole SameSite attribute, the octet caps, the control-character check over the entire header, the 400-day lifetime limit and the "a Secure cookie needs a secure origin" rule are not in RFC 6265 — they come from draft-ietf-httpbis-rfc6265bis, an Internet-Draft that is still being revised, and a further draft (draft-ietf-httpbis-layered-cookies) now intends to obsolete both documents. Every entry in rules therefore carries a specSource of either RFC 6265 or rfc6265bis draft, so you can see exactly which claims are standardized and which are not.

Deliberate limits. The Domain attribute is not checked against the Public Suffix List — Domain=co.uk is reported with the verdict not-checked, never as a pass, because a real browser would reject it. Because accepted, stored and wouldBeSent are single booleans, they can only report "no rule failed", which means they assume the not-checked rule passes; whenever that assumption is what produces a positive verdict a warning says so explicitly, so a broad Domain never silently reads as fine. Per-browser cookie count and total-size limits, cookie eviction and Partitioned/CHIPS partitioning are not modelled at all. Where browser behaviour does appear it is labelled as such and never presented as spec: Chrome's Lax-allowing-unsafe grace window is named in a warning rather than applied, Partitioned and Priority are reported as unrecognized attributes, and treating http://localhost as a secure connection is flagged as the user-agent choice RFC 6265 leaves open. /match models a safe request method, which matters for Lax: an unsafe cross-site top-level navigation such as a form POST would not carry a Lax cookie. On /match the single at instant is both when the cookie was received and when the request happens, so use Expires rather than Max-Age to model a cookie that has already aged out.

Do not paste a real session cookie into the query string. Use a placeholder value. Nothing is stored or looked up — the answer is computed from your input alone — but a query string still travels through browser history, proxies and server logs like every other part of a URL.

Use it for

  • Debug why a Set-Cookie your server sent never shows up in the browser
  • Check a __Host- or __Secure- cookie against the prefix rules before shipping
  • Decide whether a session cookie survives a cross-site subresource request or a link click
  • Work out the default path a cookie gets when the Path attribute is omitted
  • Confirm that Max-Age=0 deletes a cookie that also carries a future Expires

Frequently asked questions

Why isn't my cookie being set?

Send the header to /api/cookies/parse together with the URL that set it. The accepted flag plus the rules trace name every rule that failed — a Domain that does not domain-match the origin, SameSite=None without Secure, a broken name prefix — while rejectedAttributes lists anything that was parsed and thrown away, such as an Expires value that did not parse.

Why is my SameSite=None cookie rejected?

SameSite=None is only honoured together with the Secure attribute; without it the cookie is ignored entirely. That rule lives in the rfc6265bis draft, not in RFC 6265, and the response labels it rfc6265bis draft for exactly that reason.

What are the __Host- prefix requirements?

Three things, all checked here: the Secure attribute, no Domain attribute at all, and an explicit Path=/ — a default-path that merely happens to be / does not satisfy the rule. Miss any one and prefixVerdict is fail with prefixFailure naming it. __Secure- only requires Secure.

Does Max-Age or Expires win when both are set?

Max-Age wins, always — RFC 6265 §5.3 uses Expires only when Max-Age is absent. So Max-Age=0 deletes the cookie even alongside an Expires years in the future. effectiveExpiry reports the winner after the rfc6265bis §5.5 400-day lifetime limit, so a two-year Max-Age comes back reduced to 400 days with a warning.

What path does my cookie get if I don't send a Path attribute?

The origin URL's default-path: everything up to but not including the right-most /. A cookie set from https://example.com/a/b/c gets /a/b, so it is not sent to /a/d. The defaultPath field shows it for any origin URL you pass.

Does this endpoint flag a Domain attribute that is too broad, like Domain=co.uk?

No, and it says so twice: the public-suffix rule carries the verdict not-checked, and when the cookie is otherwise accepted a warning states that the positive verdict only stands because that rule was skipped. Consulting the Public Suffix List is deliberately out of scope for this version, so check broad Domain values against publicsuffix.org yourself.

Standards & references