HTTP Cache-Control Header Calculator
The Cache-Control HTTP header tells browsers, proxies, and CDNs how - and for how long - a response may be cached. Getting it wrong is one of the most common causes of stale content being served to users, or of servers being hammered with requests that should have been served from cache. This tool builds a syntactically correct Cache-Control header from a handful of plain options and explains what each directive actually does.
What is Cache-Control?
Cache-Control is a response header defined by RFC 9111 (the HTTP Caching specification). A typical value looks like:
Cache-Control: public, max-age=3600, s-maxage=600, stale-while-revalidate=86400
Each comma-separated part is a directive. Some directives take a numeric argument (like max-age=3600), others are standalone flags (like must-revalidate).
The directives this calculator covers
- Cacheability - exactly one of:
public- any cache (browser, proxy, CDN) may store the response, even if it would normally be considered private (e.g. it had anAuthorizationheader).private- only the end user's browser may cache it; shared caches like CDNs must not.no-cache- caches may store the response, but must revalidate with the origin server on every use before serving it.no-store- nothing may be cached at all; every request goes to the origin.
max-age=<seconds>- how long the response is considered fresh from the moment it was generated.s-maxage=<seconds>- likemax-age, but only applies to shared caches (CDNs, reverse proxies); overridesmax-agefor them. Ignored by browsers.stale-while-revalidate=<seconds>- after freshness expires, the cache may keep serving the stale copy for this many extra seconds while it fetches a fresh one in the background.stale-if-error=<seconds>- if the origin server errors while revalidating, the cache may serve the stale copy for this many extra seconds instead of showing an error.must-revalidate- once the response is stale, it must not be served again without successful revalidation - overridesstale-while-revalidate/stale-if-errorfor that cache.immutable- tells the browser the response body will never change while it's fresh, so it can skip revalidation entirely even on a user-triggered reload.no-transform- forbids intermediate proxies from modifying the response body (e.g. re-compressing images or minifying text).
How this calculator works
For a shared cache such as a CDN, s-maxage (when present) always takes priority over max-age; browsers ignore s-maxage entirely and only ever look at max-age. The calculator builds the header string directive-by-directive in the canonical order (cacheability type first, then the numeric freshness directives, then the boolean flags), skips any directive left at zero/off, and shows the resulting duration broken down into seconds, minutes, hours, and days so it's easy to sanity-check.
Worked example
Suppose you're serving a versioned static asset (like app.a1b2c3.js) that never changes once published, through a CDN:
- Cache type:
public - Max-Age:
31536000(1 year) - s-maxage:
0(not needed - CDN can just followmax-age) - Immutable:
Yes
This produces:
Cache-Control: public, max-age=31536000, immutable
Browsers will cache this asset for a full year and never re-check it - exactly right for a filename that changes every time the content does.
For an API response that should be fresh for 30 seconds but can tolerate serving slightly stale data for up to 5 minutes while it refreshes in the background, you'd instead use:
- Cache type:
private - Max-Age:
30 - Stale-While-Revalidate:
300
Cache-Control: private, max-age=30, stale-while-revalidate=300
How to use this tool
- Choose the cacheability type (
public,private,no-cache, orno-store). - Enter
Max-Agein seconds (leave at0to omit it). - Optionally set
s-maxage,stale-while-revalidate, andstale-if-errorfor finer CDN/edge-cache control. - Toggle
must-revalidate,immutable, andno-transformas needed. - Copy the generated header value straight into your server, reverse proxy, or CDN configuration.