Productivity and Utilities

Cache-Control Header Explainer

Paste a Cache-Control value to see what each directive means and how long a cache can reuse the response.

Your numbers

Only the value, for example public, max-age=3600. Leave empty to use Expires or the heuristic.

How long the response has already been in caches. Leave 0 for a fresh response.

More options

Format: Mon, 05 Oct 2026 12:00:00 GMT. Needed to use Expires or Last-Modified.

Result

Time left before a check

10 minutes

Reusable without contacting the origin for 10 minutes more

Freshness lifetime
10 minutes
Lifetime comes from
s-maxage
Age so far
0 seconds
Cache type
Shared (CDN, proxy)
Stale-while-revalidate
1 minute
Stale-if-error
Not set
Issues found
1

Each directive

DirectiveMeaningApplies to this cache
publicAny cache may store the response, even where it would not by defaultYes
max-age=3600Seconds the response stays freshYes
s-maxage=600Seconds it stays fresh in shared caches, overriding max-age thereYes
stale-while-revalidate=60Seconds a stale copy may be served while it is refreshed in the backgroundYes
How this was calculated
  1. Pick the freshness lifetime. A shared cache uses s-maxage first. Otherwise max-age is used, then Expires minus Date, then a heuristic from Last-Modified.
  2. Subtract the Age header from the lifetime. While the result is above zero the response is fresh and can be reused without asking the origin.
  3. no-store stops caching altogether. no-cache allows storing but demands a check before each reuse. private keeps a response out of shared caches.
  4. A shared cache uses s-maxage and ignores max-age and Expires.
  • s-maxage is shorter than max-age, so shared caches refresh sooner than browsers do.
  • This follows the rules of RFC 9111 for a stored response. It cannot know the behavior of a particular CDN or browser, which can add their own settings. Nothing you type leaves this page.

Calculated using SumPanda.com · https://sumpanda.com/http-cache-control-explainer/

Results are estimates for general information. Verify important figures before relying on them.

Next step

How to use the cache-control header explainer

  1. Paste the value of a Cache-Control header, such as public, max-age=3600. Leave it empty if you only have Expires or Last-Modified headers.
  2. Choose whether you mean a shared cache such as a CDN or proxy, or a private browser cache, and enter the Age header if you have one.
  3. Open the extra fields to add the Date, Expires and Last-Modified headers when a response relies on them.
  4. Read the time left, the freshness lifetime and where it came from, the table of directives and any conflicts the page found.

Formula

lifetime = s-maxage (shared caches only), else max-age, else Expires - Date, else 10% of (Date - Last-Modified)

time left = lifetime - Age; the response is fresh while this is above zero

an invalid or negative freshness value counts as stale

These are the freshness rules of RFC 9111. Expires is ignored when max-age is present, and the heuristic is only a fallback that caches may apply differently.

Browser against CDN

With Cache-Control: public, max-age=600, s-maxage=60 a shared cache keeps the response fresh for 1 minute, because s-maxage replaces max-age there. A browser ignores s-maxage and keeps it fresh for 10 minutes.

With no Cache-Control header, a Date of Mon, 05 Oct 2026 12:00:00 GMT and an Expires of one hour later, the lifetime is 1 hour. An Age of 300 seconds leaves 55 minutes. A value such as Expires: 0 is not a valid date, so caches treat the response as already expired.

Directives that people confuse

No-cache does not mean do not cache. It lets a cache store the response but requires it to check with the origin before every reuse. No-store is the directive that forbids storing at all. Private keeps a response out of shared caches, while public allows storing even where a cache would not by default.

Must-revalidate only matters once a response is stale, and immutable only helps when a lifetime is set, which is why the checker points out those directives when no lifetime is given.

Conflicts the page looks for

It flags a no-store with a max-age, which can have no effect, public together with private, private together with s-maxage, no-cache together with immutable, a quoted or non-numeric max-age, a repeated directive, and Expires combined with max-age. It also lists directives it does not know.

The result describes the rules, not a particular product. A CDN or browser can add its own settings. Look up what a response code means with the HTTP Status Codes Reference.

Assumptions and limits

  • Freshness follows RFC 9111 for a stored response. Request directives such as max-stale and min-fresh are explained but not applied.
  • Dates must be in the standard HTTP format, for example Mon, 05 Oct 2026 12:00:00 GMT.
  • The heuristic lifetime assumes a response that may be stored by default and is only one way a cache may choose.
  • Age is the number of seconds in the Age header. The page cannot know how long a response has actually been stored.
  • Nothing typed here leaves your browser.

Formulas reviewed October 10, 2026. See the calculation methodology for how SumPanda rounds, tests and sources its formulas.

Frequently asked questions

What is the difference between max-age and s-maxage?

Max-age sets the freshness lifetime for every cache. S-maxage sets it only for shared caches such as a CDN, and replaces max-age there, so the same response can live for different times in different places.

Why does an invalid max-age make a response stale?

A cache that cannot read the lifetime has no safe number to use, so it must treat the response as stale and ask the origin again. That is why a value such as max-age=1h does not work.

Does stale-while-revalidate extend the lifetime?

It adds a window after the response goes stale in which the cache may still serve it while it fetches a fresh copy in the background. The lifetime itself does not change.

What does the Age header add?

It says how long the response has already sat in caches along the way. The time left is the lifetime minus that age, so a response that was cached for a minute upstream has a minute less to live here.