Skip to navigation

malevolent design weblog

This blog is now defunct, but you can find more stuff over at my personal site

Using HTTP Status Codes

Yes, it’s another nitpicking investigation of web development minutiae!

When a web server responds to a request, it sends an HTTP status code to let the browser/cache/search engine know what’s going on. Most sites don’t use them as much as they could; here’s a list of some of the codes web developers might want to trigger in certain circumstances, followed by implementation tips:

Useful status codes

301 Moved Permanently
This is followed by a ‘Location:’ header to specify the new URL. It’s vital to use 301s when pages move, so that search engines are kept informed and PageRank is transferred intact.
302 Found
This is like 301, but used for temporarily redirecting (e.g. sending the browser elsewhere after successfully submitting a form). Strictly speaking, ‘307 Temporary Redirect’ is the correct code (since HTTP/1.1), but 302 is far more widely used.
400 Bad Request
Use this when the site has received a malformed or clearly invalid request. For example, this could happen if someone tampers with a URL to put non-numeric data where only a number can ever normally occur.
403 Forbidden
If a user simply tries to browse an area of a site that requires a login, you’ll want to handle it gracefully and direct them to a login form. However, for restricted areas no one should be innocently stumbling into it’s appropriate to react more harshly and just show an error page.
404 Not Found
Strictly speaking, ‘410 Gone’ is the correct HTTP/1.1 code for permanently-removed content, but the vaguer 404 (might be temporary, might be permanent) is more widely used and easier to deal with (for 410 you may have to keep track of removed pages indefinitely).
500 Internal Server Error
Use this one if something goes fatally wrong; maybe a database query has failed, or a file that should be there isn’t.
503 Service Unavailable
This is a way of saying “Back soon!”. If you’re tampering with the site you should take it offline by returning a friendly 503 holding page for every request (if you just send the holding page with a normal status code then a search engine has no way of knowing it shouldn’t replace the content in its index).

Setting Apache’s error pages

You can specify the pages Apache displays when it throws errors either via the httpd.conf or (more likely for shared hosting) in a .htaccess file. For example, I’m using this in the root .htaccess of a site:

ErrorDocument 400 /_errors/400.html
ErrorDocument 403 /_errors/403.html
ErrorDocument 404 /_errors/404.html
ErrorDocument 500 /_errors/500.html
ErrorDocument 503 /_errors/503.html

The pages should be helpful, non-technical and simple; create a minimal layout rather than trying to use the normal page template. Keep them self-contained, with any images etc. held within the error pages’ folder.

Triggering errors from code

You can reuse the Apache error pages for errors thrown by the site’s code. A PHP function to throw a 503 might look something like:

function serviceUnavailable($diagnostics = '')
  header('HTTP/1.1 503 Service Unavailable');
  header('Content-type: text/html; charset=utf-8');
  echo '<!-- '.htmlspecialchars($diagnostics).' -->';

Obviously you can’t do this after anything’s been sent to the browser, but if you sensibly keep your page templates separate then that’s rarely an issue (as all output is after application logic and file/database access is safely out of the way).

Safe redirects

Be careful about redirecting to URLs passed to the page (e.g. via the query string); many sites’ redirect pages are vulnerable to HTTP Response Splitting.

Going offline for maintenance

In a file that’s loaded at the start of each page (e.g. your framework, file containing settings, or stub file that receives all requests), put in a commented-out call to a ‘503 Service Unavailable’ function (or use a variable/constant that’s checked and acted upon elsewhere). Whenever you’re doing maintenance you can easily take the whole site down by uncommenting it.


Also important to remember that if you are creating 301 redirects to ensure that they work for HTTP 1.0 as well as 1.1, if you want all the search engine spiders to recognise them.

Yahoo's 'slurp' for one still uses HTTP 1.0.

Daniel, 23rd Apr, 9:56am

Surely Yahoo! must be comfortable with HTTP/1.1 in practice? Slurp certainly makes use of the Host header (otherwise it'd only be able to access sites on dedicated IPs) and doesn't freak out when pages are served with 1.1, I don't know if redirects are a special case though.

Matt Round, 23rd Apr, 3:12pm

Comments are now closed for this entry.