200 and 404

The two numbers your site answers with

Your website answers every knock with a number. You have met one of them. The other one is quieter, and it can lie to you.

You know 404: the "page not found" you get from a dead link. Door closed. Fewer people know its opposite, 200, which is the server saying "yes, here it is." The door opened. When it works you never see it, it is the quiet number behind every page that loads. That is the whole vocabulary. 200 means yes. 404 means there is nothing here. Everything else is a variation.

So why should this matter to someone who does not read code? Because a server can be set up to answer 200 to things that are not there.

The lie

Picture your shop. A customer asks for a product you do not stock. The honest answer is "we do not have that." A site that answers 200 instead says "certainly, right this way," and hands them your front door again.

Ask for a page that never existed and you get your homepage. Ask for /.env, a file that can hold passwords and keys, and you get your homepage. The server is not leaking the file. It is doing something subtler and, in its way, worse: it is telling every asker that everything is fine.

Who is knocking

The first is a scanner. Attackers do not try one door. They walk the whole street, trying addresses in bulk: /.env, /.git/config, /admin, /backup.zip. On a healthy site most of those come back 404 and the scanner moves on. On a site that answers 200 to everything, every door looks real. Nothing has leaked, but a stranger now believes your building is larger than it is, and writes your name down to come back later.

The second asker is your own monitoring. Most uptime and link checkers read the status code and stop there. 200 means fine. So when something genuinely breaks, a deleted product, a mistyped link, a form that stopped loading, and the server answers 200 anyway, no alarm goes off. The tool that exists to tell you something is wrong is told everything is right. You find out from a customer, or you never find out.

That is the part people miss. A false 200 is rarely a hole in itself. It is a broken smoke alarm. It does not start the fire. It makes sure you sleep through it.

How I found mine

Not in a lab. On my own site. For two weeks, rowanvexley.com answered every wrong address with a real page and a 200. It came from how the site was hosted: when a page was missing, the host handed back the homepage with a smile instead of an honest 404.

The fix was one file. A page whose only job is to say "not here," named 404.html, placed where the site gets built. The next deploy, the wrong addresses started telling the truth.

Check yours in thirty seconds

You do not need me, and you do not need to install anything.

With a terminal (macOS: Terminal; Windows: PowerShell). Paste these one at a time, swapping in your own domain:

curl -sI https://yourstore.com/ | head -1
curl -sI https://yourstore.com/does-not-exist | head -1

The first should say 200. The second should say 404. If the second says 200, your site is smiling at a door that is not there.

Without a terminal. Open your store, press F12 (or right-click and choose Inspect), and click the Network tab. Type a nonsense path like yourstore.com/does-not-exist into the address bar and hit enter. Watch the Status column. 404 is honest. 200 means the same problem mine had.

If the second answer surprises you, that is the whole reason I wrote this. Send me the URL and I will write up the cause and the smallest fix, free.

Send a storefront URL

← More writing