---
title: Deployed, but users still see the old page? How to check with the HTTP Headers checker
description: You shipped a fix, it shows on your machine, and users still get the old version. The answer is in the response headers: Cache-Control, Age and the CDN's cache status say who served the page and how old it is. Here's how to check HTTP headers from outside your network with the free HTTP Headers checker, how to read the caching ones, and what to change when a stale copy is the problem.
canonical: https://watchfor.io/blog/how-to-check-http-headers
---

# Deployed, but users still see the old page? How to check with the HTTP Headers checker

2026-10-04 · WatchFor Team · Guides · guides, http, cdn

You shipped a fix, it shows on your machine, and users still get the old version. The answer is in the response headers: Cache-Control, Age and the CDN's cache status say who served the page and how old it is. Here's how to check HTTP headers from outside your network with the free HTTP Headers checker, how to read the caching ones, and what to change when a stale copy is the problem.

To check HTTP headers, request the URL and print the response headers
instead of the page. For a "users still see the old version" problem, four
of them answer it: `Cache-Control` says how long caches may keep the page,
`Age` says how many seconds the copy you got has been sitting in a cache,
`Last-Modified` or `ETag` identify the version, and a CDN header such as
`X-Cache` or `CF-Cache-Status` says whether the edge served it from cache.

The free [HTTP Headers checker](/http-header-checker) fetches the URL from a
WatchFor probe and lists every response header with the status code and a
timing breakdown. No signup.

## What this tool answers

*What does this URL send back right now, header by header, to a fresh
visitor?* Reach for it when a deploy doesn't show up for everyone, when you
suspect a CDN is caching what it shouldn't (or not caching what it should),
when a redirect or CORS problem only happens in production, or when you need
to know which server or CDN actually answered. It runs from a probe with no
cookies and no browser cache, so your own cached copy can't hide anything.

## A real example

### Checking HTTP headers when a change doesn't show up for users

The usual report: "I fixed the homepage an hour ago, I can see it, but the
customer still sees the old one." We showed what the headers reveal on a
busy page that sits behind a cache: the Wikipedia portal.

In the [HTTP Headers checker](/http-header-checker) we entered
`https://www.wikipedia.org/`, kept **GET** and **Follow redirects** and
pressed **Fetch headers**. The run came from the Vilnius probe:

![The HTTP Headers checker result for https://www.wikipedia.org/: status 200, TTFB 108 ms, connect 30 ms, TLS 36 ms, security headers 1 of 7, and the response headers Age 10020, Cache-Control s-maxage=86400, must-revalidate, max-age=3600, Content-Length 22767, Date Sat, 03 Oct 2026 19:21:31 GMT, Etag W/"16f03-65c8ce6864540" and Last-Modified Mon, 28 Sep 2026 15:41:33 GMT](/blog/how-to-check-http-headers-cache.webp)

Status **200**, first byte after 108 ms. The headers that matter:

- **`Cache-Control: s-maxage=86400, must-revalidate, max-age=3600`**:
  shared caches (the CDN) may keep it 24 hours, browsers 1 hour.
- **`Age: 10020`**: this copy had been in the cache for 2 h 47 min.
- **`Date: Sat, 03 Oct 2026 19:21:31 GMT`**: when the copy was generated;
  `Date` plus `Age` is the moment we asked.
- **`Last-Modified: Mon, 28 Sep 2026 15:41:33 GMT`**: the version of the
  page itself.
- **`X-Cache: cp3066 miss, cp3066 hit/472542`** and
  **`X-Cache-Status: hit-front`**: Wikimedia's edge served it from its
  front cache, where this object had been hit 472,542 times.

The page wasn't built for us. A cache server near the probe handed over a
copy made 2 h 47 min earlier, and the `Cache-Control` header allows it to do
that for up to 24 hours. A browser that loaded it may reuse its own copy for
an hour without asking again.

**The answer:** for your own site, read the same four headers on the URL
the user sees. If `Age` is high and the CDN reports a hit, they're getting
the cached copy, and the fix is one of:

- **Purge the URL at the CDN** after each deploy (Cloudflare: Caching →
  Purge Cache; most CDNs have an API for it, and deploy pipelines can call
  it).
- **Cache HTML for less time** at the edge (a smaller `s-maxage`), or let the
  edge revalidate with the origin using the `ETag`.
- **Version your assets** (`app.3f9c1.js`) so a new HTML page never points
  at an old cached script.

If `Age` is `0` and the CDN reports a miss, the server is sending the old
version itself: the deploy didn't reach every server, or an
application-level cache is still warm.

A high `Age` isn't a fault on its own: here the page hadn't changed since
28 September. It only becomes a problem when the page changed and the cached
copy wasn't purged.

## How to read the results

| What you see | What it means |
| --- | --- |
| **Status** | The final response's status code. Green 2xx, amber 3xx, red 4xx/5xx. |
| **TTFB chip** | Time to first byte. A cache hit is usually much faster than a miss that goes to the origin. |
| **Redirects chip** | How many redirects were followed to get here. Untick **Follow redirects** to see the first response alone. |
| **DNS / connect / TLS / TTFB** | Where the time went, in order. |
| **Security headers (n/7)** | Which common security headers came back. See the [security headers guide](/blog/how-to-check-security-headers). |
| **Header list** | Every response header in the order received, security headers in green. Long values and cookies are shortened. |

Caching headers worth knowing:

| Header | Read it as |
| --- | --- |
| `Cache-Control: max-age=N` | Browsers (and CDNs, unless `s-maxage` is set) may reuse it for N seconds |
| `s-maxage=N` | Shared caches only, overrides `max-age` for them |
| `no-cache` / `no-store` / `private` | Revalidate every time / never store / browser only, no CDN |
| `Age` | Seconds the copy has spent in caches |
| `CF-Cache-Status`, `X-Cache` | The CDN's verdict: HIT, MISS, EXPIRED, BYPASS, DYNAMIC (names vary) |
| `ETag`, `Last-Modified` | Version identifiers used to revalidate with a 304 |
| `Vary` | Which request headers produce different cached copies |

## More ways to use it

- **Who is serving my site?** `Server`, `Via` and CDN-specific headers name
  the CDN or server that answered, handy after a DNS change.
- **CORS errors in production.** Check that `Access-Control-Allow-Origin`
  comes back on the URL the browser complains about.
- **Compression.** `Content-Encoding: gzip` or `br` confirms the response was
  compressed; the [Brotli checker](/brotli-checker) compares sizes.
- **A cache that never hits.** Many CDNs, Cloudflare's defaults included,
  won't cache a response that carries `Set-Cookie`. A session cookie on
  every page is a common reason the CDN always reports a miss.

## Tips and gotchas

- **The probe's cache is not your user's.** A CDN has many edges; the probe
  hits the one near it. A user in another region may get an older or newer
  copy.
- **HEAD can differ from GET.** Some servers and CDNs answer HEAD from a
  different code path. Keep **GET** unless you have a reason.
- **Your browser caches too.** If headers here show the new version and you
  still see the old one, hard-reload or open a private window.
- **Header names are case-insensitive.** HTTP/2 sends them lowercase;
  `Cache-Control` and `cache-control` are the same header.
- **Only response headers.** The checker sends a standard request; to send
  custom request headers or a body, use the [API tester](/api-tester).

## Check it from the command line too

`curl -sI` prints the headers of a HEAD request:

```bash
curl -sI https://www.wikipedia.org/ | grep -iE '^(HTTP|cache-control|age|last-modified|etag|x-cache)'
```

```text
HTTP/2 200
cache-control: s-maxage=86400, must-revalidate, max-age=3600
etag: W/"16f03-65c8ce6864540"
last-modified: Mon, 28 Sep 2026 15:41:33 GMT
age: 83700
x-cache: cp3074 miss, cp3074 hit/4748682
x-cache-status: hit-front
```

Same page version (`ETag` and `Last-Modified` match), but from our machine a
different cache server (`cp3074`) answered with a copy 23 hours old. Two
edges, two ages: exactly why one user can see an old page while another
sees the new one. To compare edges or bypass a cache for a test, add a
throwaway query string: `curl -sI 'https://example.com/?nocache=1'`.

## Keep watching it

When a header matters (a `Cache-Control` value that must stay, a CORS
header, a CDN status), an [API monitor](/api-monitoring) requests the URL on
a schedule and asserts on response headers like any other field: for
example, header `Cache-Control` **contains** `max-age=3600`, or header
`Access-Control-Allow-Origin` **exists**. A failing assertion opens an
incident with the expected and actual value side by side.

## FAQ

**How do I check the HTTP headers of a website?**
Use the HTTP Headers checker, run `curl -I https://example.com` in a
terminal, or open your browser's developer tools, go to the Network tab,
click the page request and read **Response Headers**.

**How do I know if my page is served from the CDN cache?**
Look for the CDN's cache header (`CF-Cache-Status: HIT` on Cloudflare,
`X-Cache: HIT` on many others) and a non-zero `Age`. A MISS or `Age: 0`
means the origin built the response.

**Why do users see an old version of my site after a deploy?**
A cache still has the old copy: the CDN (until its `s-maxage` or `max-age`
runs out or you purge it) or the user's browser. Check `Cache-Control` and
`Age` on the affected URL, purge the CDN, and version your static assets. The
[guide to speeding up your website](/blog/how-to-speed-up-your-website)
covers cache settings that don't backfire.

---

Canonical page: https://watchfor.io/blog/how-to-check-http-headers · All articles: https://watchfor.io/blog/all.md · Site guide: https://watchfor.io/llms.txt
