A not found response tells you nothing about whether your pages are server rendered
An empty shell from a url that does not exist looks exactly like a rendering failure, and mistaking one for the other produced the most alarming wrong finding this programme has ever reported about its own site.
Published by AI Knows Us · Updated 19 October 2026
Check the status code before you conclude anything about rendering. A missing url and an unrendered page both return a document with the furniture in it and no article text, and in a terminal they are indistinguishable. We proved this against ourselves. Somebody assembled a url from a slug, received a 404 carrying an 18KB shell with no article element in it, and reported that no blog body on this site was server rendered. The page was live under a different path the whole time, and that article comes back byte for byte identical to eleven agent strings at HTTP 200, 63KB uncompressed and 1,789 words. The finding was false and it was the worst possible finding for a company that sells being read correctly by machines.
The hour it cost is the reason this page exists. The error is not exotic, it is not a failure of care, and the person who made it was running exactly the right kind of check. It is a confusion between two responses that are genuinely hard to tell apart unless you look at one specific field first.
Why the two look identical
On a modern site built as a single application, the not found route is served by the same shell as everything else. The server returns the head, the navigation, the footer and an empty content region, and the router decides afterwards that there is nothing to put in it. An unrendered page does the same thing for a different reason: the shell arrives and the content is written in later by a script that a plain client never runs.
Same symptom, opposite causes, opposite fixes. One is a url problem you solve by finding the right url. The other is a rendering problem you solve inside your application. Guessing between them is a coin flip with a very expensive wrong side.
| What came back | Status | Size | Article text |
|---|---|---|---|
| A url that does not exist on this site | 404 | 18KB | None |
| A real article, any of eleven agent strings | 200 | 63KB | 1,789 words |
Those two rows are from the same site on the same day. The difference between them is three and a half times the bytes and the entire content of the page, and the only field that would have told you which one you were holding before you measured either is the status code.
The three checks, in the order that settles it
- Read the status first, every time. Not the body, not the size, the status. A 404 ends the enquiry: you have learned nothing about rendering and you need a different url.
- Fetch a url you already know is good. This is the control arm and it takes one command. If the known good url returns a full article and your suspect url returns a shell, the suspect url is the problem.
- Measure inside the article boundary, not the whole document. A shell and a full page differ by thousands of words of readable text inside one element. Counting the whole document mixes that signal with framework payload and tells you much less.
Run in that order the whole question takes about ninety seconds, which is less time than writing up a false finding takes.
Where the wrong url came from, and the rule that followed
The url was built by hand from a slug, and that is the root cause rather than the rendering check. This site serves pages under two different path prefixes, and a page that is live under one of them returns a 404 under the other. A slug is a fragment of a url and not a url, so assembling one is a guess with a plausible failure mode.
The fix is dull and total: read the sitemap and use the url it gives you. Every check in this programme now starts there, and the reason a sitemap is worth maintaining properly rather than generating and forgetting is covered in our page on when a sitemap actually matters.
How to test your own site for rendering, correctly
The real question is narrower than whether your site is server rendered, and it is per fact rather than per site. Pick the facts you most want quoted about your business, in words, before you look at any code. Then for each one, fetch the page that holds it with a plain client and search the raw response for that exact string.
- Take every url from your sitemap rather than from your content management system or your memory.
- Record the status of every hop and the final url, because a redirect into the wrong place and a missing page produce similar looking disappointment.
- Record the response size and whether the target string was present, yes or no. Those two fields separate a delivery failure from a rendering failure.
- Repeat one page under a browser string as your control. If the browser arm fails too, you are looking at access rather than rendering.
What a non rendering client actually receives, measured across the ten domains most cited in our own audit, is set out with the counts in our page on the first response and what is in it. The short version is that volume of text is not the lever and the presence of your specific facts is.
Questions about empty responses, 404s and rendering tests
My page came back with no text. Is my site client rendered?
Check the status before answering that. A 404 or a 403 produces an empty looking body for reasons that have nothing to do with rendering, and only a 200 with an empty content region is evidence about how your application serves pages.
How big is a shell compared with a real page?
On this site the missing page response is 18KB with no article in it and a real article is 63KB carrying 1,789 words. Measure your own pair once and you will recognise your own shell instantly afterwards, which is worth more than any general rule about sizes.
Does a soft 404 behave the same way?
A soft 404 is worse for this purpose, because it returns a 200 with no content and removes the one field that would have saved you. The defence is the control arm: fetch a url you know is good in the same session and compare.
Why not just use a browser to check?
Because a browser runs the scripts, so it shows you the page after the step a plain client never performs. Use a browser to confirm what a person sees and a plain client to see what arrives first. The gap between the two readings is the finding.
What if the alarming finding turns out to be true?
Then you will have confirmed it from a url you took out of the sitemap, with a known good control beside it, and you can act on it with confidence. The checks that disprove a false alarm are the same checks that make a real one defensible.
Ninety seconds against an hour
The whole of this page reduces to one command run in the wrong order. Status first, then a known good url, then the article boundary. Done that way the enquiry ends correctly in a minute and a half; done the other way round it produced a false claim about our own product and an hour spent chasing it. A sceptical reader is entitled to ask what else we have got wrong, and the answer is kept in public: the exports, the windows and the dated blind scan behind every figure we publish sit on our proof page, corrections included. Diagnosing this layer on client sites, and telling them which of the two problems they actually have, is the service we charge for. For what a finding looks like when the honest result is that nothing happened, our page on a flat reading being the finding is the closest companion to this one.