Not sure why but all of my error pages respond with a 200. That's feels a little strange to me, the pages exist but shouldn't they have their corresponding status codes? How do I get Nginx to render my 404 pages with a 404 status code?

For example:

▶ curl -I http://example.com/404
HTTP/1.1 200 OK <<--------------------------- WTF! THIS SHOULD BE 404!!
Server: nginx/1.8.0
Date: Tue, 17 Apr 2018 02:24:04 GMT
Content-Type: text/html; charset=UTF-8

Here is the relevant part of my config:

server {

listen 80 default_server;

server_name example.com;
root /var/www/example/static;
index index.html;

try_files $uri $uri/ $uri.html =404;

# error pages
error_page 400 =400 /400; # bad request
error_page 401 =401 /401; # unauthorized
error_page 403 =403 /403; # forbidden
error_page 404 =404 /404; # not found
error_page 408 =408 /408; # timeout
error_page 500 502 503 504 =500 /500; # error


In the documentation is states:

... it is possible to change the response code ... using the “=response” syntax

It is true that the page exist but having set an error_page in the config should change that page's status. For example, if you curl Google's 404 you get the correct result:

curl -I https://www.google.com/404
HTTP/2 404  <<--------------------------- Ahhh, much better.
content-type: text/html; charset=UTF-8
referrer-policy: no-referrer
content-length: 1564

I need my 404 page to produce a 404 status code since I redirect to it from other parts of my app. This is fine for humans but bad for machines since a redirect produces a 302 followed by a 200 instead of a 404.

  • 3
    I don't know anything about Nginx, but you're asking for the error page itself, which is being returned correctly, hence the 200. An error has not occurred. – joeqwerty Apr 17 '18 at 2:47

As joeqwerty said in a comment, nginx is correctly returning 200 because you asked for a document that exists. You would only get a 404 if you requested a document that does not exist. Try doing that instead. (And whether such a document exists on some other server is completely irrelevant.)

  • I'll edit the question to make what I'm asking more clear. – jwerre Apr 17 '18 at 5:29
  • 3
    @jwerre instead of calling curl -I http://example.com/404 try calling something like curl -I http://example.com/404_this_is_random_rubbish and you should see the 404 you expect. If you call your actual 404 page directly (rather than have it delivered in response to another bad page request) then the correct response is 200 - as the page requested does exist. – Barry Pollard Apr 17 '18 at 17:08
  • 2
    @jwerre you have no idea if that is Google's 404 page and therefore if it does exit, or if it is 404.html or /errors/404 or some other thing. Why do you assume they have put the 404 page in the same location as you? Or that it's even a static page at all? The correct thing to do is to return 200 if the actual page is referenced and this is what your server is doing. Why do you "need" your 404 page to produce a 404 status? That is incorrect behavior and, while it may be possible to do this using rewrites you risk breaking serving of that page for real 404s. It's way more effort than it's worth. – Barry Pollard Apr 17 '18 at 18:11
  • 1
    @jwerre then what your app is doing is wrong. All that will do is a 302 followed by a 404 - which is still wrong! It should return a 404 directly and return HTML making up a 404 page (which can either be the 404 page you have created and stored outside your app, or a different one stored inside your app - which may have the exact same contents as the one stored outside your app). – Barry Pollard Apr 17 '18 at 18:16
  • 2
    @jwerre So give the 404 page a URL that isn't likely to be guessed so easily. That's what everyone else does. – Michael Hampton Apr 17 '18 at 19:06

Configure NGINX to point to that page for genuine 404 errors. Once that’s done, when you want to redirect your app in places just redirect them to a bogus page

A previous answer said it correctly, when you’re pulling your 404 page at it’s genuine place, it will return a 200, because you’ve requested a page that does exist.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.