Is your WordPress page really cached?
A cached page skips PHP and the database entirely. The response headers tell you whether that happened.
Written by Hamza Ahmad Aslam. Updated . One of the caching and speed guides.
What the checker sees
It reads the cache status headers hosts and CDNs send: cf-cache-status, x-cache, x-litespeed-cache, x-vercel-cache, x-nginx-cache, x-kinsta-cache, x-cache-enabled, x-proxy-cache and x-sucuri-cache. A value containing HIT, or an Age header above zero, means the page came from a cache.
It also looks for the marks caching plugins leave in the HTML: WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache, Cache Enabler, WP Fastest Cache, NitroPack and Breeze. A cache that exists but missed is reported apart from no cache at all.
Read it yourself
Ask twice. The first request after a purge is allowed to miss; the second should not.
curl -sI https://example.com/ | grep -iE 'cache|^age'
curl -sI https://example.com/ | grep -iE 'cache|^age'On Cloudflare, cf-cache-status: DYNAMIC means Cloudflare did not try to cache the page. That is its default for HTML: it caches images, CSS and scripts, and needs a Cache Rule before it stores pages.
Why pages miss
- Cookies. Caches skip visitors with a login cookie (
wordpress_logged_in_…), and many skip anyone with a WooCommerce cart or session cookie. A plugin that sets a cookie for every visitor turns the cache off for everyone. Cache-Control: no-store,privateormax-age=0from a plugin or theme. PHP sessions sendno-storeby default, so one plugin callingsession_start()on every page is enough.- Query strings.
?utm_source=…and similar make a separate cache entry for each value unless the cache is told to ignore them. - The cache was just purged, or the page is rarely visited and expired.
Fix it
Use one page cache, not three. A managed host's own cache or a CDN rule is usually the fastest. A caching plugin is the fallback on shared hosting. Whichever you pick, bypass it for logged-in users, the cart and checkout, and cache everything else for anonymous visitors.
If the checker reported Cache-Control forbidding caching, find what sends it: disable plugins one at a time on a staging copy and rerun the curl -sI command after each.
Check the fix
Run the check twice. The second report should say the page came from a cache, and the time to first byte should drop with it.
More detail in Caching WordPress pages at the CDN on hamzaahmadaslam.com.
Check a site for this
Other fixes
- Read and reduce time to first byte on WordPressUnder 300 ms looks like a cached page. Over 800 ms usually means PHP and the database are doing work on every visit.
- Hide the WordPress version numberThe version shows in the page's generator tag and in the stock readme.html. Both can go in a few minutes.
- Stop the WordPress REST API listing user namesThe users endpoint answers anonymous requests with account slugs, which are usually the login names.