Staaarter

Cache Header Checker

Parses a response's caching headers (Cache-Control, Expires, ETag, Last-Modified, Vary, Age), breaks Cache-Control's comma-separated directive list into individual flags, explains what the combination means in practice, and flags contradictory or redundant directive combinations. A free online tool from Staaarter, right in your browser.

Runs locallyUpdated 2026-08-04
By Staaarter Team
checkerliveperformance

Overview

Introduction

Cache-Control is one comma-separated header that packs in several independent decisions at once - who's allowed to cache a response, for how long, and whether they need to check back with the origin before reusing it - which makes a real-world value like "private, no-cache, max-age=0, must-revalidate" hard to parse at a glance even for people who work with HTTP daily.

This tool breaks that directive list apart, explains the combination in plain terms, and cross-checks it against Expires, ETag, Last-Modified, Vary, and Age to point out contradictions or redundant legacy headers.

What Is Cache Header Checker?

A caching-header decoder that parses Cache-Control's directive list (max-age, no-cache, no-store, public/private, must-revalidate, immutable, and others) into individual flags and explains what the resulting combination means for how the response gets cached and reused.

It also reads Expires, ETag, Last-Modified, Vary, and Age alongside Cache-Control, since those headers interact with each other rather than each mattering in isolation.

How Cache Header Checker Works

The Cache-Control value is split on commas, each directive is lowercased and separated into a name and optional value (e.g. max-age=3600 becomes {name: "max-age", value: "3600"}), and the resulting flags are used to build a one-sentence plain-English summary of the overall caching behavior.

A small set of rule checks then looks for known contradictions (no-store combined with a max-age, must-revalidate combined with no-cache) and legacy overlaps (Cache-Control alongside Expires) and surfaces each as a note.

When To Use Cache Header Checker

While debugging why a page or asset isn't caching the way you expect, to see the exact combination of directives being sent rather than guessing from the raw string.

When reviewing a CDN or server config change to caching headers, to confirm the resulting Cache-Control value says what you intended and doesn't contain a leftover contradictory directive.

Features

Advantages

  • Breaks a dense, easy-to-misread directive string into individual labeled flags instead of leaving you to parse commas and equals signs by eye.
  • Distinguishes a genuine contradiction (no-store plus max-age) from a harmless legacy overlap (Cache-Control plus Expires), instead of flagging both the same way.
  • Covers the headers that actually interact with Cache-Control (ETag, Last-Modified, Vary, Age) in one view instead of requiring five separate lookups.

Limitations

  • Only reads standard Cache-Control directive names; a nonstandard or vendor-specific directive (e.g. a CDN's proprietary flag) is parsed as a name/value pair but not specifically explained.
  • As with any header-based checker on this site, security- and cache-relevant headers are often invisible on a live cross-origin fetch unless the target explicitly exposes them via CORS - paste headers from curl -I or DevTools for a complete, reliable check.

Examples

A long-lived, fingerprinted static asset

Input

Cache-Control: public, max-age=31536000, immutable

Output

public, max-age=31536000: cacheable by both the browser and shared/CDN caches for 1 year.
Directives: public, max-age=31536000, immutable

immutable additionally tells supporting browsers to skip revalidation entirely for the life of max-age, appropriate here since the filename presumably changes (e.g. via a content hash) whenever the content does.

A contradictory combination

Input

Cache-Control: no-store, max-age=3600

Output

no-store: this response must never be written to any cache.
Note: Contradictory - "no-store" is combined with "max-age=3600". no-store overrides everything else and wins.

The max-age value is unreachable dead configuration since no-store instructs every cache to skip storing the response entirely.

Best Practices & Notes

Best Practices

  • Use immutable only on assets whose URL changes whenever their content does (content-hashed filenames), since it tells browsers to skip revalidation entirely for the life of max-age even on a hard refresh.
  • Prefer a single clear Cache-Control value over layering Cache-Control and Expires together going forward; the overlap is harmless but adds a maintenance burden of keeping two headers in sync for no behavioral benefit in modern caches.

Developer Notes

Directive parsing lowercases directive names but preserves value casing and strips wrapping quotes (some servers quote directive values); max-age is coerced to a Number for the contradiction checks, and a non-numeric max-age value is treated as NaN and skipped by those checks rather than throwing.

Cache Header Checker Use Cases

  • Debugging why a browser keeps re-fetching an asset you expected to be cached, by seeing the exact parsed directives instead of the raw string
  • Auditing a CDN configuration change to confirm the resulting Cache-Control header doesn't contain a contradictory or redundant directive combination
  • Explaining to a teammate unfamiliar with HTTP caching what a specific Cache-Control value actually does in practice

Common Mistakes

  • Setting must-revalidate expecting it to force a cache-busting refresh, when it only changes what happens once the response is already stale - it does nothing while max-age hasn't expired yet.
  • Applying a short max-age to a response that also carries the immutable directive, which undermines the point of immutable (skipping revalidation for the cache's lifetime) by giving it almost no lifetime to skip revalidation during.

Tips

  • When in doubt about whether a cache actually honored your headers, check the response's Age header on a repeat request - a nonzero Age confirms it was served from a cache rather than freshly generated.

References

Frequently Asked Questions