How do I skip wordpress's 404 handling and redirect all 404 errors for static files to 404.html?

I read and it seems its not possible when using permalinks?

The objective is to reduce the server load for 404 errors by not loading php.

7 Answers 7


.htaccess skip WordPress 404 error handling for static files.

<IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_URI} !(robots\.txt|sitemap\.xml(\.gz)?)
        RewriteCond %{REQUEST_FILENAME} \.(css|js|html|htm|rtf|rtx|svg|svgz|txt|xsd|xsl|xml|asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|pdf|png|pot|pps|ppt|pptx|ra|ram|swf|tar|tif|tiff|wav|wma|wri|xla|xls|xlsx|xlt|xlw|zip)$ [NC]
        RewriteRule .* - [L]

Note: These rules were generated by the W3 Total Cache plugin*

Nginx skip WordPress 404 handling for static files.

if (-f $request_filename) {
if (-d $request_filename) {
if ($request_uri ~ "(robots\.txt|sitemap\.xml(\.gz)?)") {
if ($request_uri ~* \.(css|js|html|htm|rtf|rtx|svg|svgz|txt|xsd|xsl|xml|asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|pdf|png|pot|pps|ppt|pptx|ra|ram|swf|tar|tif|tiff|wav|wma|wri|xla|xls|xlsx|xlt|xlw|zip)$) {
    return 404;
  • Nice! Find more 404 filename extensions from your logs with: sed -rn '/" 404 /s/^.*\.([a-z]+) HTTP.*$/\1/igp' log/access_log | sort | uniq May 17, 2020 at 0:19

To extend on what Chris_O said....I would install W3 Total Cache and use the settings from that plugin to not cache static files. The plugin in itself is very useful and a must to speed up your site, especially with the latest update.

Also I recommend you have a look at Creating an Error 404 Page from Wordpress to see how to handle 404 for static files, 403 (forbidden), etc. Its a good read.


Maybe a simple solution. Use the conditional tag is_404() and create an redirect to your static file; include the code in the file header.php or index.php of the theme.

Here a example.

   if ( is_404() ) {
      wp_redirect( 'static.htm' );


  • 2
    the decision making is still done in PHP here and not at htaccess level. The aim is to skip the loading of PHP altogether for 404 errors. Aug 2, 2011 at 5:19
  • 2
    @freethinker: right, only via php; the way via htaccess is faster, but maybe not so easy handling in WordPress
    – bueltge
    Aug 2, 2011 at 19:41
  • @kaiser oops, updated the question Aug 2, 2011 at 23:44

I'm not sure that this is possible. If you look at the htaccess code that WordPress creates when you enable permalinks, it basically says: "If the file/directory cannot be found, send it to index.php." This includes all actual 404 requests. Outside of creating a list of every dynamically-generated public resource that WordPress knows of and directly inserting this into .htaccess, you'll need to load php to handle the 404's.


I liked the idea of Chris_O, but I made my own version, which is more safe.

So what I did, I just added folders to exception, so if your requests starts from those lines - it's definitely not a valid permalink. The majority of requests are coming from bots that are trying to check the contents of those folders for exploits. They will be effectively filtered, and if needed you can display some small static 404 page.

Other requests will still be handled by wordpress, and if someone enters a wrong address it will display a user friendly not found message within your template. The solution of Chris_O will only work for requests that look like file extensions, otherwise they will also be handled by wordpress.

To make it even more reliable, you can retrieve your raw access file and search for 404 errors. If you notice many requests that start with particular lines, you can also include them to this filter:

#adding your own handler
ErrorDocument 404 /404/index.html

<IfModule mod_rewrite.c>
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_URI} !^/(404|cgi-bin|wp-admin|wp-content|wp-includes)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

I have multiples CMS installed on my site so I use something like this to use the same 404 error page for all CMS's. I use this conf for Nginx+FastCgi and it's working fine:

server {
    error_page 404 /404.html; #enable custom 404 error page
    location ~ /\.ht {
        deny all; #disable access to htaccess
    location ~ [^/]\.php(/|$) {
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_intercept_errors on; #disable PHP 404 error intercept
    location /wordpress/ {
        try_files $uri $uri/ /wordpress/index.php?$args;

I use this config together with this in php.ini :

cgi.fix_pathinfo = 1 

wordpress is installed like this http://example.com/wordpress/ . the 404.html is located in the root of the http://example.com/ .

P.S. Do not forget that PHP and Nginx services need to be restarted after making changes to the php.ini or nginx.conf files for the changes to take effect.


There are 3 ways of doing this

  1. By changing your 404.php code.
  2. By using wordpress plugins.
  3. By editing your .htaccess file .

Complete tutorial - (link dead and redirected to spam)

  • Hi Mazhar, could you post a full answer, rather than just a link to your site. If that link dies, this answer will be pretty much useless! Cheers! Sep 27, 2012 at 9:35
  • this page gives a 404. Ironic. Or are you trying to say something? Sep 16, 2015 at 2:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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