cacheControl string The response Cache-Control field value. Both token and quoted-string arguments are accepted; unrecognized directives are reported and ignored.
Compute RFC 9111 cache behavior from your headers: storability, freshness lifetime, current age, fresh/stale verdict and the stale-while-revalidate window.
Authoritative reference data or standards computation
Evaluates one stored response against RFC 9111 §3 (storability), §4.2.1–§4.2.3 (freshness lifetime and current age) and RFC 5861 (stale windows). now defaults to the current instant, so a bare query answers “right now”.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
cacheControl | string | allowed: ≤ 2048 example: public, max-age=60, s-maxage=600, stale-while-revalidate=30 | The response Cache-Control field value. Both token and quoted-string arguments are accepted; unrecognized directives are reported and ignored. |
date | date | example: 2026-01-15T10:00:00Z | The response Date header as an ISO 8601 instant. When omitted, the reception time is used (RFC 9110 §6.6.1). |
expires | date | example: 2026-01-15T10:10:00Z | The response Expires header as an ISO 8601 instant. Used only when neither s-maxage (shared) nor max-age applies. |
age | int | allowed: 0 – 2147483648 example: 120 | The response Age header in seconds; feeds correctedAgeValue in the RFC 9111 §4.2.3 calculation. |
lastModified | date | example: 2026-01-01T10:00:00Z | The response Last-Modified header as an ISO 8601 instant. Required for heuristic freshness. |
requestTime | date | example: 2026-01-15T09:59:59Z | When the request that produced this response was sent. Defaults to responseTime (a zero-delay exchange). |
responseTime | date | example: 2026-01-15T10:00:00Z | When the response was received. Defaults to requestTime, then to the Date header, then to now. |
now | date | example: 2026-01-15T10:05:00Z | The instant to evaluate at. Defaults to the current time, which is echoed in the response and in meta.params. |
shared | boolean | default: true example: false | Model a shared cache (proxy/CDN) rather than a private browser cache. Controls s-maxage, private and Authorization handling. |
heuristicFactor | float | default: 0.1 allowed: 0 – 1 example: 0.25 | Fraction of the Date − Last-Modified interval used for heuristic freshness. RFC 9111 §4.2.2 calls 10% typical but mandates no heuristic. |
authorization | boolean | default: false example: true | Whether the request carried an Authorization header field, which restricts shared-cache storage under RFC 9111 §3.5. |
status | int | default: 200 allowed: 100 – 599 example: 404 | Response status code. Decides whether the response is final and whether RFC 9110 §15.1 makes it heuristically cacheable. |
cacheControl string The response Cache-Control field value. Both token and quoted-string arguments are accepted; unrecognized directives are reported and ignored.
date date The response Date header as an ISO 8601 instant. When omitted, the reception time is used (RFC 9110 §6.6.1).
expires date The response Expires header as an ISO 8601 instant. Used only when neither s-maxage (shared) nor max-age applies.
age int The response Age header in seconds; feeds correctedAgeValue in the RFC 9111 §4.2.3 calculation.
lastModified date The response Last-Modified header as an ISO 8601 instant. Required for heuristic freshness.
requestTime date When the request that produced this response was sent. Defaults to responseTime (a zero-delay exchange).
responseTime date When the response was received. Defaults to requestTime, then to the Date header, then to now.
now date The instant to evaluate at. Defaults to the current time, which is echoed in the response and in meta.params.
shared boolean Model a shared cache (proxy/CDN) rather than a private browser cache. Controls s-maxage, private and Authorization handling.
heuristicFactor float Fraction of the Date − Last-Modified interval used for heuristic freshness. RFC 9111 §4.2.2 calls 10% typical but mandates no heuristic.
authorization boolean Whether the request carried an Authorization header field, which restricts shared-cache storage under RFC 9111 §3.5.
status int Response status code. Decides whether the response is final and whether RFC 9110 §15.1 makes it heuristically cacheable.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
fields | list | example: now,requestTime | Return only these fields (comma-separated). Mutually exclusive with 'exclude'. |
exclude | list | example: withinStaleIfError | Return all fields except these (comma-separated). |
pretty | boolean | default: false example: true | Pretty-print the JSON response. |
unwrap | boolean | default: false example: true | Drop the envelope: return the raw array/object without data/meta wrapper. |
fields list Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude list Return all fields except these (comma-separated).
pretty boolean Pretty-print the JSON response.
unwrap boolean Drop the envelope: return the raw array/object without data/meta wrapper.
| Field | Type | Description | Example |
|---|---|---|---|
now | string (ISO 8601) | Evaluation instant; the server's current time when the 'now' parameter is omitted. | 2026-01-15T10:05:00.000Z |
requestTime | string (ISO 8601) | Resolved RFC 9111 §4.2.3 request_time — when the request that produced the stored response was sent. | 2026-01-15T10:00:00.000Z |
responseTime | string (ISO 8601) | Resolved RFC 9111 §4.2.3 response_time — when the response was received by the cache. | 2026-01-15T10:00:00.000Z |
shared | boolean | Whether a shared (proxy/CDN) cache was modeled rather than a private browser cache. | true |
heuristicallyCacheable | boolean | Whether RFC 9110 §15.1 defines this status code as heuristically cacheable. | true |
storable | boolean | Whether every RFC 9111 §3 storage condition this calculator models is satisfied. | true |
storabilityReasons | string[] | One sentence per RFC 9111 §3 condition that forbids storing the response; empty when storable. | [] |
freshnessLifetimeSeconds nullable | integer | RFC 9111 §4.2.1 freshness_lifetime in seconds; null when no explicit rule matched and no heuristic applies. Capped at 2147483648 whichever rule produced it (§1.2.2), with a warning. Can be negative when Expires precedes Date. | 600 |
freshnessSource nullable | string | Which rule produced the lifetime: s-maxage, max-age, expires or heuristic; null when none did. | s-maxage |
apparentAge | integer | max(0, responseTime − Date) in whole seconds (RFC 9111 §4.2.3). | 0 |
responseDelay | integer | responseTime − requestTime in whole seconds (RFC 9111 §4.2.3). | 0 |
correctedAgeValue | integer | Age header value plus responseDelay (RFC 9111 §4.2.3). | 120 |
correctedInitialAge | integer | max(apparentAge, correctedAgeValue) — the conservative form from RFC 9111 §4.2.3. | 120 |
residentTime | integer | now − responseTime in whole seconds; negative when the evaluation instant precedes the response. | 300 |
currentAge | integer | correctedInitialAge + residentTime — the value a cache would put in the Age header. | 420 |
fresh | boolean | RFC 9111 §4.2: freshnessLifetime > currentAge. False whenever no freshness lifetime exists. Computed independently of storable — check that first. | true |
staleSeconds nullable | integer | How far currentAge has passed the freshness lifetime (0 while fresh); null when no lifetime exists. | 0 |
mustRevalidate | boolean | Whether RFC 9111 §4.2.4 forbids serving this response once stale — set by an unqualified no-cache, must-revalidate, or proxy-revalidate/s-maxage in a shared cache. Not merely an echo of the must-revalidate directive. A qualified no-cache="field-name" does not set it (§5.2.2.4). | true |
requiresRevalidation | boolean | True when the response cannot be reused from cache without contacting the origin: it is not storable at all, an unqualified no-cache is present, or it is not fresh. | false |
staleWhileRevalidateWindow nullable | integer | The stale-while-revalidate window in seconds (RFC 5861 §3): null when the directive is absent, 0 when it is present with an unusable argument. | 30 |
withinStaleWhileRevalidate | boolean | True when the response is stale, staleSeconds is at or inside the window, and no directive forbids stale reuse. | false |
staleIfErrorWindow nullable | integer | The stale-if-error window in seconds (RFC 5861 §4): null when the directive is absent, 0 when it is present with an unusable argument. | 1200 |
withinStaleIfError | boolean | True when an origin error right now could still be answered from this stale stored response. | false |
now string (ISO 8601) Evaluation instant; the server's current time when the 'now' parameter is omitted.
example: 2026-01-15T10:05:00.000Z
requestTime string (ISO 8601) Resolved RFC 9111 §4.2.3 request_time — when the request that produced the stored response was sent.
example: 2026-01-15T10:00:00.000Z
responseTime string (ISO 8601) Resolved RFC 9111 §4.2.3 response_time — when the response was received by the cache.
example: 2026-01-15T10:00:00.000Z
shared boolean Whether a shared (proxy/CDN) cache was modeled rather than a private browser cache.
example: true
heuristicallyCacheable boolean Whether RFC 9110 §15.1 defines this status code as heuristically cacheable.
example: true
storable boolean Whether every RFC 9111 §3 storage condition this calculator models is satisfied.
example: true
storabilityReasons string[] One sentence per RFC 9111 §3 condition that forbids storing the response; empty when storable.
example: []
freshnessLifetimeSeconds integer nullable RFC 9111 §4.2.1 freshness_lifetime in seconds; null when no explicit rule matched and no heuristic applies. Capped at 2147483648 whichever rule produced it (§1.2.2), with a warning. Can be negative when Expires precedes Date.
example: 600
freshnessSource string nullable Which rule produced the lifetime: s-maxage, max-age, expires or heuristic; null when none did.
example: s-maxage
apparentAge integer max(0, responseTime − Date) in whole seconds (RFC 9111 §4.2.3).
example: 0
responseDelay integer responseTime − requestTime in whole seconds (RFC 9111 §4.2.3).
example: 0
correctedAgeValue integer Age header value plus responseDelay (RFC 9111 §4.2.3).
example: 120
correctedInitialAge integer max(apparentAge, correctedAgeValue) — the conservative form from RFC 9111 §4.2.3.
example: 120
residentTime integer now − responseTime in whole seconds; negative when the evaluation instant precedes the response.
example: 300
currentAge integer correctedInitialAge + residentTime — the value a cache would put in the Age header.
example: 420
fresh boolean RFC 9111 §4.2: freshnessLifetime > currentAge. False whenever no freshness lifetime exists. Computed independently of storable — check that first.
example: true
staleSeconds integer nullable How far currentAge has passed the freshness lifetime (0 while fresh); null when no lifetime exists.
example: 0
mustRevalidate boolean Whether RFC 9111 §4.2.4 forbids serving this response once stale — set by an unqualified no-cache, must-revalidate, or proxy-revalidate/s-maxage in a shared cache. Not merely an echo of the must-revalidate directive. A qualified no-cache="field-name" does not set it (§5.2.2.4).
example: true
requiresRevalidation boolean True when the response cannot be reused from cache without contacting the origin: it is not storable at all, an unqualified no-cache is present, or it is not fresh.
example: false
staleWhileRevalidateWindow integer nullable The stale-while-revalidate window in seconds (RFC 5861 §3): null when the directive is absent, 0 when it is present with an unusable argument.
example: 30
withinStaleWhileRevalidate boolean True when the response is stale, staleSeconds is at or inside the window, and no directive forbids stale reuse.
example: false
staleIfErrorWindow integer nullable The stale-if-error window in seconds (RFC 5861 §4): null when the directive is absent, 0 when it is present with an unusable argument.
example: 1200
withinStaleIfError boolean True when an origin error right now could still be answered from this stale stored response.
example: false
/api/http-caching/freshness?cacheControl=public%2C%20max-age%3D60%2C%20s-maxage%3D600&date=2026-01-15T10%3A00%3A00Z&age=120&now=2026-01-15T10%3A05%3A00Z {
"data": {
"now": "2026-01-15T10:05:00.000Z",
"requestTime": "2026-01-15T10:00:00.000Z",
"responseTime": "2026-01-15T10:00:00.000Z",
"shared": true,
"heuristicallyCacheable": true,
"storable": true,
"storabilityReasons": [],
"freshnessLifetimeSeconds": 600,
"freshnessSource": "s-maxage",
"apparentAge": 0,
"responseDelay": 0,
"correctedAgeValue": 120,
"correctedInitialAge": 120,
"residentTime": 300,
"currentAge": 420,
"fresh": true,
"staleSeconds": 0,
"mustRevalidate": true,
"requiresRevalidation": false,
"staleWhileRevalidateWindow": null,
"withinStaleWhileRevalidate": false,
"staleIfErrorWindow": null,
"withinStaleIfError": false
},
"meta": {
"endpoint": "http-caching",
"route": "/freshness",
"params": {
"cacheControl": "public, max-age=60, s-maxage=600",
"date": "2026-01-15T10:00:00.000Z",
"age": 120,
"now": "2026-01-15T10:05:00.000Z",
"shared": true,
"heuristicFactor": 0.1,
"authorization": false,
"status": 200,
"requestTime": "2026-01-15T10:00:00.000Z",
"responseTime": "2026-01-15T10:00:00.000Z"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/http-caching/freshness?cacheControl=public%2C%20max-age%3D60%2C%20s-maxage%3D600&date=2026-01-15T10%3A00%3A00Z&age=120&now=2026-01-15T10%3A05%3A00Z&shared=false {
"data": {
"now": "2026-01-15T10:05:00.000Z",
"requestTime": "2026-01-15T10:00:00.000Z",
"responseTime": "2026-01-15T10:00:00.000Z",
"shared": false,
"heuristicallyCacheable": true,
"storable": true,
"storabilityReasons": [],
"freshnessLifetimeSeconds": 60,
"freshnessSource": "max-age",
"apparentAge": 0,
"responseDelay": 0,
"correctedAgeValue": 120,
"correctedInitialAge": 120,
"residentTime": 300,
"currentAge": 420,
"fresh": false,
"staleSeconds": 360,
"mustRevalidate": false,
"requiresRevalidation": true,
"staleWhileRevalidateWindow": null,
"withinStaleWhileRevalidate": false,
"staleIfErrorWindow": null,
"withinStaleIfError": false
},
"meta": {
"endpoint": "http-caching",
"route": "/freshness",
"params": {
"cacheControl": "public, max-age=60, s-maxage=600",
"date": "2026-01-15T10:00:00.000Z",
"age": 120,
"now": "2026-01-15T10:05:00.000Z",
"shared": false,
"heuristicFactor": 0.1,
"authorization": false,
"status": 200,
"requestTime": "2026-01-15T10:00:00.000Z",
"responseTime": "2026-01-15T10:00:00.000Z"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/http-caching/freshness?cacheControl=no-store%2C%20max-age%3D3600 {
"data": {
"now": "2026-07-29T08:13:22.000Z",
"requestTime": "2026-07-29T08:13:22.000Z",
"responseTime": "2026-07-29T08:13:22.000Z",
"shared": true,
"heuristicallyCacheable": true,
"storable": false,
"storabilityReasons": [
"The 'no-store' response directive forbids storing any part of this response (RFC 9111 §5.2.2.5)."
],
"freshnessLifetimeSeconds": 3600,
"freshnessSource": "max-age",
"apparentAge": 0,
"responseDelay": 0,
"correctedAgeValue": 0,
"correctedInitialAge": 0,
"residentTime": 0,
"currentAge": 0,
"fresh": true,
"staleSeconds": 0,
"mustRevalidate": false,
"requiresRevalidation": true,
"staleWhileRevalidateWindow": null,
"withinStaleWhileRevalidate": false,
"staleIfErrorWindow": null,
"withinStaleIfError": false
},
"meta": {
"endpoint": "http-caching",
"route": "/freshness",
"params": {
"cacheControl": "no-store, max-age=3600",
"shared": true,
"heuristicFactor": 0.1,
"authorization": false,
"status": 200,
"now": "2026-07-29T08:13:22.000Z",
"requestTime": "2026-07-29T08:13:22.000Z",
"responseTime": "2026-07-29T08:13:22.000Z"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/http-caching/freshness?date=2026-01-15T10%3A00%3A00Z&lastModified=2026-01-01T10%3A00%3A00Z&now=2026-01-15T10%3A30%3A00Z {
"data": {
"now": "2026-01-15T10:30:00.000Z",
"requestTime": "2026-01-15T10:00:00.000Z",
"responseTime": "2026-01-15T10:00:00.000Z",
"shared": true,
"heuristicallyCacheable": true,
"storable": true,
"storabilityReasons": [],
"freshnessLifetimeSeconds": 120960,
"freshnessSource": "heuristic",
"apparentAge": 0,
"responseDelay": 0,
"correctedAgeValue": 0,
"correctedInitialAge": 0,
"residentTime": 1800,
"currentAge": 1800,
"fresh": true,
"staleSeconds": 0,
"mustRevalidate": false,
"requiresRevalidation": false,
"staleWhileRevalidateWindow": null,
"withinStaleWhileRevalidate": false,
"staleIfErrorWindow": null,
"withinStaleIfError": false
},
"meta": {
"endpoint": "http-caching",
"route": "/freshness",
"params": {
"date": "2026-01-15T10:00:00.000Z",
"lastModified": "2026-01-01T10:00:00.000Z",
"now": "2026-01-15T10:30:00.000Z",
"shared": true,
"heuristicFactor": 0.1,
"authorization": false,
"status": 200,
"requestTime": "2026-01-15T10:00:00.000Z",
"responseTime": "2026-01-15T10:00:00.000Z"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/http-caching/freshness?cacheControl=max-age%3D600%2C%20stale-if-error%3D1200&date=2026-01-15T10%3A00%3A00Z&age=900&now=2026-01-15T10%3A00%3A00Z {
"data": {
"now": "2026-01-15T10:00:00.000Z",
"requestTime": "2026-01-15T10:00:00.000Z",
"responseTime": "2026-01-15T10:00:00.000Z",
"shared": true,
"heuristicallyCacheable": true,
"storable": true,
"storabilityReasons": [],
"freshnessLifetimeSeconds": 600,
"freshnessSource": "max-age",
"apparentAge": 0,
"responseDelay": 0,
"correctedAgeValue": 900,
"correctedInitialAge": 900,
"residentTime": 0,
"currentAge": 900,
"fresh": false,
"staleSeconds": 300,
"mustRevalidate": false,
"requiresRevalidation": true,
"staleWhileRevalidateWindow": null,
"withinStaleWhileRevalidate": false,
"staleIfErrorWindow": 1200,
"withinStaleIfError": true
},
"meta": {
"endpoint": "http-caching",
"route": "/freshness",
"params": {
"cacheControl": "max-age=600, stale-if-error=1200",
"date": "2026-01-15T10:00:00.000Z",
"age": 900,
"now": "2026-01-15T10:00:00.000Z",
"shared": true,
"heuristicFactor": 0.1,
"authorization": false,
"status": 200,
"requestTime": "2026-01-15T10:00:00.000Z",
"responseTime": "2026-01-15T10:00:00.000Z"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/http-caching/freshness?cacheControl=no-cache%3D%22set-cookie%22%2C%20max-age%3D600&date=2026-01-15T10%3A00%3A00Z&now=2026-01-15T10%3A01%3A00Z {
"data": {
"now": "2026-01-15T10:01:00.000Z",
"requestTime": "2026-01-15T10:00:00.000Z",
"responseTime": "2026-01-15T10:00:00.000Z",
"shared": true,
"heuristicallyCacheable": true,
"storable": true,
"storabilityReasons": [],
"freshnessLifetimeSeconds": 600,
"freshnessSource": "max-age",
"apparentAge": 0,
"responseDelay": 0,
"correctedAgeValue": 0,
"correctedInitialAge": 0,
"residentTime": 60,
"currentAge": 60,
"fresh": true,
"staleSeconds": 0,
"mustRevalidate": false,
"requiresRevalidation": false,
"staleWhileRevalidateWindow": null,
"withinStaleWhileRevalidate": false,
"staleIfErrorWindow": null,
"withinStaleIfError": false
},
"meta": {
"endpoint": "http-caching",
"route": "/freshness",
"params": {
"cacheControl": "no-cache=\"set-cookie\", max-age=600",
"date": "2026-01-15T10:00:00.000Z",
"now": "2026-01-15T10:01:00.000Z",
"shared": true,
"heuristicFactor": 0.1,
"authorization": false,
"status": 200,
"requestTime": "2026-01-15T10:00:00.000Z",
"responseTime": "2026-01-15T10:00:00.000Z"
},
…
]
}
} Splits a Cache-Control field value into its directives, validates each argument against the grammar RFC 9111 defines for it, and reports duplicates, wrong-direction and unrecognized names.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
cacheControl
required
| string | allowed: 1 – 2048 example: public, max-age=60, s-maxage=600, stale-while-revalidate=30 | Cache-Control field value with 1–32 directives. Malformed syntax is a 400; unrecognized directive names are reported, not rejected. |
direction | enum | default: response allowed: request | response example: request | Which directive set to validate against: RFC 9111 §5.2.1 request directives or §5.2.2 response directives. |
cacheControl string required Cache-Control field value with 1–32 directives. Malformed syntax is a 400; unrecognized directive names are reported, not rejected.
direction enum Which directive set to validate against: RFC 9111 §5.2.1 request directives or §5.2.2 response directives.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
fields | list | example: cacheControl,direction | Return only these fields (comma-separated). Mutually exclusive with 'exclude'. |
exclude | list | example: canonical | Return all fields except these (comma-separated). |
pretty | boolean | default: false example: true | Pretty-print the JSON response. |
unwrap | boolean | default: false example: true | Drop the envelope: return the raw array/object without data/meta wrapper. |
fields list Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude list Return all fields except these (comma-separated).
pretty boolean Pretty-print the JSON response.
unwrap boolean Drop the envelope: return the raw array/object without data/meta wrapper.
| Field | Type | Description | Example |
|---|---|---|---|
cacheControl | string | The Cache-Control field value exactly as supplied. | public, max-age=60 |
direction | string | Which directive set was applied: request or response. | response |
count | integer | Number of cache-directive members parsed, including repeated names. | 2 |
directives | object[] | Every member in field order with its lowercased name, unquoted argument, parsed delta-seconds, quoting, duplicate/recognized/applicable flags, argument problem and defining section. | [{"name":"public","value":null,"seconds":null,"quoted":false,"duplicate":false,"recognized":true,"applicable":true,"problem":null,"reference":"RFC 9111 Section 5.2.2.9"},{"name":"max-age","value":"60","seconds":60,"quoted":false,"duplicate":false,"recognized":true,"applicable":true,"problem":null,"reference":"RFC 9111 Section 5.2.2.1"}] |
duplicates | string[] | Directive names that appear more than once; RFC 9111 §4.2.1 uses the first occurrence. | [] |
unrecognized | string[] | Directive names not defined by RFC 9111 or RFC 5861, which a cache must ignore (§5.2.3). | ["immutable"] |
notApplicable | string[] | Recognized directives that have no meaning in this direction, such as max-stale in a response. | [] |
invalid | string[] | Directives whose argument violates the syntax RFC 9111 or RFC 5861 defines for them. | [] |
canonical | string | Re-serialization of the honored directives with lowercased names and repeats, unrecognized and wrong-direction members removed. Always a field value a sender may legally generate: an argument RFC 9111 §5.2 does not define for the directive is dropped, a malformed field-name list falls back to the unqualified form, and a delta-seconds directive with a missing or unusable argument is left out entirely (it stays listed in invalid, and /freshness still counts it as present and worth 0 seconds). | public, max-age=60 |
cacheControl string The Cache-Control field value exactly as supplied.
example: public, max-age=60
direction string Which directive set was applied: request or response.
example: response
count integer Number of cache-directive members parsed, including repeated names.
example: 2
directives object[] Every member in field order with its lowercased name, unquoted argument, parsed delta-seconds, quoting, duplicate/recognized/applicable flags, argument problem and defining section.
example: [{"name":"public","value":null,"seconds":null,"quoted":false,"duplicate":false,"recognized":true,"applicable":true,"problem":null,"reference":"RFC 9111 Section 5.2.2.9"},{"name":"max-age","value":"60","seconds":60,"quoted":false,"duplicate":false,"recognized":true,"applicable":true,"problem":null,"reference":"RFC 9111 Section 5.2.2.1"}]
duplicates string[] Directive names that appear more than once; RFC 9111 §4.2.1 uses the first occurrence.
example: []
unrecognized string[] Directive names not defined by RFC 9111 or RFC 5861, which a cache must ignore (§5.2.3).
example: ["immutable"]
notApplicable string[] Recognized directives that have no meaning in this direction, such as max-stale in a response.
example: []
invalid string[] Directives whose argument violates the syntax RFC 9111 or RFC 5861 defines for them.
example: []
canonical string Re-serialization of the honored directives with lowercased names and repeats, unrecognized and wrong-direction members removed. Always a field value a sender may legally generate: an argument RFC 9111 §5.2 does not define for the directive is dropped, a malformed field-name list falls back to the unqualified form, and a delta-seconds directive with a missing or unusable argument is left out entirely (it stays listed in invalid, and /freshness still counts it as present and worth 0 seconds).
example: public, max-age=60
/api/http-caching/parse?cacheControl=public%2C%20max-age%3D60%2C%20s-maxage%3D600%2C%20stale-while-revalidate%3D30 {
"data": {
"cacheControl": "public, max-age=60, s-maxage=600, stale-while-revalidate=30",
"direction": "response",
"count": 4,
"directives": [
{
"name": "public",
"value": null,
"seconds": null,
"quoted": false,
"duplicate": false,
"recognized": true,
"applicable": true,
"problem": null,
"reference": "RFC 9111 Section 5.2.2.9"
},
{
"name": "max-age",
"value": "60",
"seconds": 60,
"quoted": false,
"duplicate": false,
"recognized": true,
"applicable": true,
"problem": null,
"reference": "RFC 9111 Section 5.2.2.1"
},
{
"name": "s-maxage",
"value": "600",
"seconds": 600,
"quoted": false,
"duplicate": false,
"recognized": true,
"applicable": true,
"problem": null,
"reference": "RFC 9111 Section 5.2.2.10"
},
{
…
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/http-caching/parse?cacheControl=no-cache%3D%22set-cookie%22%2C%20max-age%3D%22600%22 {
"data": {
"cacheControl": "no-cache=\"set-cookie\", max-age=\"600\"",
"direction": "response",
"count": 2,
"directives": [
{
"name": "no-cache",
"value": "set-cookie",
"seconds": null,
"quoted": true,
"duplicate": false,
"recognized": true,
"applicable": true,
"problem": null,
"reference": "RFC 9111 Section 5.2.2.4"
},
{
"name": "max-age",
"value": "600",
"seconds": 600,
"quoted": true,
"duplicate": false,
"recognized": true,
"applicable": true,
"problem": null,
"reference": "RFC 9111 Section 5.2.2.1"
}
],
"duplicates": [],
"unrecognized": [],
"notApplicable": [],
"invalid": [],
"canonical": "no-cache=\"set-cookie\", max-age=600"
},
"meta": {
"endpoint": "http-caching",
"route": "/parse",
"params": {
"cacheControl": "no-cache=\"set-cookie\", max-age=\"600\"",
…
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/http-caching/parse?cacheControl=no-cache%2C%20max-stale%3D60&direction=request {
"data": {
"cacheControl": "no-cache, max-stale=60",
"direction": "request",
"count": 2,
"directives": [
{
"name": "no-cache",
"value": null,
"seconds": null,
"quoted": false,
"duplicate": false,
"recognized": true,
"applicable": true,
"problem": null,
"reference": "RFC 9111 Section 5.2.1.4"
},
{
"name": "max-stale",
"value": "60",
"seconds": 60,
"quoted": false,
"duplicate": false,
"recognized": true,
"applicable": true,
"problem": null,
"reference": "RFC 9111 Section 5.2.1.2"
}
],
"duplicates": [],
"unrecognized": [],
"notApplicable": [],
"invalid": [],
"canonical": "no-cache, max-stale=60"
},
"meta": {
"endpoint": "http-caching",
"route": "/parse",
"params": {
"cacheControl": "no-cache, max-stale=60",
…
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} Pure RFC 9111 arithmetic over the caching headers you paste in. /freshness answers the two questions a cache actually asks — may this response be stored at all? and is the stored copy still fresh? — and returns every intermediate value rather than just a verdict.
Storability follows the RFC 9111 §3 conditions in order: a non-final (1xx) status, no-store, an unqualified private in a shared cache, and an Authorization request without must-revalidate/public/s-maxage each disqualify the response — as does having no storage condition at all. Every failure comes back as a sentence in storabilityReasons, so "why was this never cached?" is answered directly.
Qualified and unqualified forms. §5.2.2.4 and §5.2.2.7 give no-cache and private two very different meanings depending on whether they carry a #field-name argument, and this endpoint keeps them apart. Unqualified private blocks shared storage and lets a private cache apply heuristic freshness; qualified private="set-cookie" does neither — it only forbids storing the named fields. Unqualified no-cache sets mustRevalidate and requiresRevalidation; qualified no-cache="set-cookie" sets neither, because §5.2.2.4 says a cache MAY reuse the response with those fields excluded (a warning says so, and notes §5.2.2.4's own remark that most caches do not implement the distinction). An argument that is not a valid field-name list — private="", no-cache="bad field" — is not a qualified form at all, so it is honored as the unqualified one: §4.2.1 says the most restrictive directive wins, and failing open on a privacy directive is the wrong way to fail.
Freshness lifetime uses the §4.2.1 first-match chain — s-maxage (shared caches only) → max-age → Expires minus Date → heuristic — and names the winner in freshnessSource. Heuristic freshness (§4.2.2) applies only when nothing explicit matched, lastModified is supplied, and the status is heuristically cacheable (200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501) or the response is explicitly marked cacheable — by public, or by an unqualified private in a private cache, which is the only form §5.2.2.7 grants that extra permission to. Its value is heuristicFactor × (Date − Last-Modified), rounded down; the 0.1 default is the fraction §4.2.2 calls typical — the RFC permits a heuristic but mandates none, so treat the number as this endpoint's documented convention, not as a standard. A directive that is present but carries an unusable argument (max-age=abc, a bare s-maxage) counts as present and worth 0 seconds, because §4.2.1 encourages treating invalid freshness information as stale rather than ignoring it. Whichever rule wins, the lifetime is capped at 2147483648 seconds with a warning — §1.2.2 requires that value whenever a delta-seconds parse or a subsequent calculation overflows, so a far-future Expires is pinned the same way max-age=99999999999999999999 is.
Age is the §4.2.3 algorithm exposed step by step: apparentAge = max(0, responseTime − Date), responseDelay = responseTime − requestTime, correctedAgeValue = Age + responseDelay, correctedInitialAge = max of the two, residentTime = now − responseTime, currentAge = correctedInitialAge + residentTime. When responseTime is omitted it falls back to requestTime, then to Date, then to now; when Date is omitted the reception time is used, per RFC 9110 §6.6.1.
no-cache is not no-store: no-cache never blocks storage, it forbids reuse without revalidation — so a response carrying it and any one §3 storage condition comes back storable: true with requiresRevalidation: true (on its own, no-cache is not a storage condition, so no-cache on a 302 or a 500 is storable: false), while no-store is storable: false no matter what else is set. requiresRevalidation is also true for anything unstorable — a no-store response is fresh by the §4.2 arithmetic yet can never be served from cache, so the origin is contacted every time. must-revalidate and, for shared caches, proxy-revalidate and s-maxage set mustRevalidate, and RFC 9111 §4.2.4's "MUST NOT generate a stale response" outranks RFC 5861's permission — so withinStaleWhileRevalidate is false when any of them applies. Many CDNs deviate here and serve stale alongside s-maxage; this endpoint models the RFC.
/parse is the syntax half: it splits #cache-directive on unquoted commas, accepts both the token and quoted-string argument forms as §5.2 requires of recipients, reports repeated directives (first wins), directives that belong to the other direction, malformed arguments and names outside RFC 9111 / RFC 5861, and re-serializes what survives. canonical is always a value a sender may legally generate, which is not the same as echoing your input back: §5.2 allows no argument on no-store/public/must-revalidate, so no-store=1 canonicalizes to no-store; a field-name list that is not one collapses to the bare directive; and max-age with a missing or non-numeric argument has no legal argument-less form, so it is dropped from canonical while still being reported in invalid. The verbatim argument is always preserved in directives[].
Scope, stated plainly. This evaluates only the values you pass in — it never fetches your URL and therefore cannot tell you whether your CDN, proxy or browser is actually configured correctly; a fresh verdict is what a conforming cache may do, not what your cache will do. Instants are supplied as ISO 8601 timestamps, not raw IMF-fixdate strings (/api/http-preconditions parses those), which also means the §5.3 rule that an unparsable Expires — famously the value 0 — means "already expired" has to be expressed by passing a past instant. The /freshness verdict does not model Vary, request cache directives such as max-stale and min-fresh (/parse still validates them), whether your cache understands a given method or status code, the must-understand override of no-store, or cache extensions that permit storage. Real caches also deviate from RFC 9111 in places; this endpoint models the RFC and says so.
s-maxage applies only to shared caches, and when present it overrides both max-age and Expires for them. Set shared=false and the same headers fall through the rest of the chain — max-age, then Expires, then a heuristic; freshnessSource always names the rule that won.
No. no-store makes the response unstorable, so /freshness returns storable: false whatever else is set. no-cache never blocks storage — it forbids reuse without revalidation — so a response carrying it plus any one RFC 9111 §3 storage condition (max-age, Expires, public, or a heuristically cacheable status) comes back storable: true with requiresRevalidation: true; no-cache is not itself a storage condition, so no-cache alone on a 302 is still storable: false. Only the unqualified form does this: a qualified no-cache="set-cookie" sets neither flag, because §5.2.2.4 lets a cache reuse the response with those fields excluded.
RFC 9111 §4.2.3: apparentAge = max(0, responseTime − Date), correctedAgeValue = Age + (responseTime − requestTime), correctedInitialAge = max of those two, and currentAge = correctedInitialAge + (now − responseTime). All six intermediates are returned so you can check the arithmetic yourself.
Compare staleSeconds with staleWhileRevalidateWindow: inside that window RFC 5861 lets a cache serve the stale copy while revalidating in the background. Note that RFC 9111 §4.2.4 forbids stale reuse whenever an unqualified no-cache, must-revalidate, proxy-revalidate or s-maxage applies, so withinStaleWhileRevalidate is false then — many CDNs deviate and serve stale anyway.
Only when no s-maxage, max-age or Expires matched, lastModified is supplied, and the status is heuristically cacheable (200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501) or the response is explicitly marked cacheable by public — or, for a private cache only, by an unqualified private (§5.2.2.7 grants that to the bare form, not to private="set-cookie"). The lifetime is heuristicFactor (default 0.1) × (Date − Last-Modified); RFC 9111 §4.2.2 permits that convention but mandates no particular heuristic.
No. It computes from the header values you paste and never makes a request, so it cannot tell you whether your CDN or browser is configured correctly — only what a conforming RFC 9111 cache would compute from those headers.
Complete pinned IANA HTTP field-name registry with status, Structured Field type, references, search and case-insensitive lookup.
Evaluate RFC 9110 conditional requests in the required precedence order, including strong/weak ETags, wildcard resources, 304 and 412 decisions.
Parse and resolve bounded RFC 9110 byte Range sets, plus validate satisfied, unknown-length and unsatisfied Content-Range field values.
The complete IANA HTTP status code registry with practical descriptions, defining RFCs and a retryable flag — list by category or look up a single code.
Parse RFC 9110 Accept media ranges and deterministically select the best available representation using specificity, parameters and q weights.
The complete IANA media type registry with file extensions merged in — look up any type or extension, or strictly parse a Content-Type value into its parts.