404′s on WordPress Permalinks (IIS with ISAPI Rewrite)

So, one day I decided to start a blog. I had available a windows server with IIS 6.0 and I PHP enabled it some time ago. After some looking around I found WordPress was what I wanted to use.  The whole installation works like a charm and with not much hassle. But for SEO reasons, I wanted to use WordPress’s permalink (common structure)  feature. For this to work you need a URL rewrite solution. Apache can use mod_rewrite here, but on IIS we could use for example Helicon’s ISAPI Rewrite Lite. I installed it following Kyle Caulfields manual. But… it didn’t work for me unfortunately.

Update (March 25th, 2011): After updating WordPress from version 2.9.2 to version 3.1 I had this problem again. See the bottom of this page for how I fixed that.

First of all, lets mention I had problems with WordPress 2.9.2 combined with ISAPI_Rewrite3 Lite on IIS 6.0. I don’t know if the problem occurs on other combinations of versions on the previously mentioned software. I’m going to tackle two problems I had with 404′s. First a 404 that came from WordPress and next a 404 from IIS.

404 from WordPress

I installed everything as mentioned above on my development server just as as Kyle Caulfield explained, I added the following code to the httpd.conf file from ISAPI_Rewrite3 Lite:

RewriteEngine on
RewriteBase /

#Exclude javascripts/stylesheets/images etc from rewriting
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

#Perform rewriting
RewriteRule ^(.*)$ index.php?p=$1 [NC,L]

After restarting IIS I could reach my blog’s home page, but as soon as I tried to go to an article I got a 404 page not found from WordPress. What is going wrong here? My assumption was that the rewrite ISAPI plugin was reached because otherwise I’d expected a 404 from IIS here. It must be the rewrite rule. To find out what could be going wrong you need to have some feedback from the system. I added the following code inside {wordpress}/index.php just below the first define statement:

echo "<pre>";
print_r($_SERVER["REQUEST_URI"] );
echo "</pre>";

This piece of code prints out the PHP server REQUEST_URI variable which tells us what the RewriteRule passes on to PHP. I went back to my browser and refreshed my page. What I found was that the rewrite rule was rewriting my URL’s to something like /index.php?p=index.php/my-first-article. Well, that’s not gonna work. The trick is now to fix the rewrite rule just so that it will give me /index.php/my-first-article. I tested that this approach works by placing it in the browser’s location bar and hitting enter. This works, so I know what I should work towards.

Back to the Rewrite Rule:

#Perform rewriting
RewriteRule ^(.*)$ index.php?p=$1 [NC,L]

I saw index.php itself getting picked up by the Regular Expression part ^(.*)$. I’m not going into explaining regex’s here, you could google it :) . Let’s update it just so it won’t pick up index.php anymore:

#Perform rewriting
RewriteRule ^(index\.php)*(.*)$ index.php?p=$2 [NC,L]

In short what I’m doing here is creating an extra regex group by surrounding to be matched values with ( and ). This is group 1. Behind it was the old group which now becomes group 2. This 2nd group is the info we need for our rewritten URL. To use this group we need to update the digit in $1 to $2.

After restarting IIS you’ll find out you’ll get the following rewritten URL: /index.php?p=/my-first-article. This is not working since WordPress expects an article number behind ?p=. Lets fix this now:

#Perform rewriting
RewriteRule ^(index\.php)*(.*)$ index.php/$2 [NC,L]

As you can see I changed the ?p= part to a slash. I restarted IIS again and it worked! Time to place my development server version to my live server…

404 from IIS

I did the exact same as mentioned above (installing WordPress and the whole URL rewrite setup) but now on my live server… I again got a… 404… WTF?! This time the 404 came from IIS and not from WordPress. What do I have to fix this time? My assumption now is that the HTTP request doesn’t reach WordPress’s PHP files at all and that the problem lies with IIS and the ISAPI rewrite filter.

I started googling and found that the problem could be the IIS Metabase was somehow corrupted. I installed a tool called IIS MetaBase Explorer. There’s also a Metabase Explorer from Microsoft which you can probably use in the same way.

I first created a backup of the MetaBase with IIS Metabase Explorer (top left button with the red arrow). Now I removed all references  I found to the ISAPI Rewrite filter (see image below) by simply clicking on them and hitting the delete button. If you installed the ISAPI Rewrite filter correctly you should be able to find it in a root folder called Filters and in a folder called filters inside a folder with a number. You can find the correct site by clicking on the numbers and search inside the key/value pairs for you website’s name:

IIS Metabase Explorer

When this was done I removed and reinstalled ISAPI Rewrite3 Lite. Remember to copy the file httpd.conf to your desktop or another place before reinstalling and then place it back in the install dir. I restarted IIS and… voila… you are looking at the result.

Upgrading WordPress 2.9.2 to WordPress 3.1

At some point I updated WordPress from version 2.9.2 to version 3.1. Al went quite well, so I zipped my backup files to store them and probably (hopefully) never to ever need them ;) . WordPress was doing fine when just checking my blog on the homepage but then I tried an article… Oh no, not again! I got infinite redirects. After some googling I found people recommending the following plugin: Permalink Fix & Disable Canonical Redirects Pack. It worked for me, so if you fixed this problem before according to my post above, this might help you again. Happy blogging!


Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.


  1. Posted April 9, 2010 at 9:26 PM | Permalink

    Great job on that!

    Also, great job on this blog. It’s looking great and even better in a CSS3 compatible browser like Chrome!

    Only needs some more posts now ;-)

  2. Almeros
    Posted April 10, 2010 at 10:50 AM | Permalink

    Thanks! Working on my next post about the CSS3 I used on this site… Coming soon.

  3. Rafael M
    Posted April 26, 2010 at 4:10 PM | Permalink

    How do you do this if you do not have access to IIS?

  4. Almeros
    Posted April 27, 2010 at 9:27 PM | Permalink

    Hi Rafael M, that’s difficult to say. What kind of access do you have then? You could ask your provider how you should fix it with the tools that are provided by them or ask them to fix this for you (and perhaps all their other customers). If they happen to get the same problem as I had, I hope Google will bring them to this article ;)

  5. lexx2gee
    Posted June 15, 2010 at 6:45 PM | Permalink

    I got Kyle Caulfields solution working fine but for some reason it breaks the .aspx page that use AJAX on my website. I get JS errors about ‘sys’ and AJAX library wont load or function.

    Any ideas why this coukld be happening when I use the simple code

    RewriteEngine on
    RewriteBase /blog
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(index\.php)*(.*)$ /blog/index.php/$2 [NC,L]

    It’s killing my brain!

  6. Almeros
    Posted June 15, 2010 at 10:04 PM | Permalink

    Hi lexx2gee, I understand the frustration you may have with this kind of stuff ;) .

    You say you work with .aspx pages? So why are you using the RewriteRule with .php in it then? Shouldn’t you at least change this to .aspx?

    I don’t know if this is the case, but in your HTML code, how do you reference external .js and .css files? If you do this with (non root) relative URL’s (src=”script.js”) instead of absolute URL’s (src=”http://yourdomain.com/script.js”) this could very well break since your browser now uses the redirected URL structure as the base for the relative URL’s.

    You can try if the use of an absolute path fixes your problem just so you know this solves it and then add rewrite rules to make your relative URL’s work again.

    Hope this’ll fix it for you!

  7. Posted June 24, 2010 at 4:47 PM | Permalink

    If you dont seem to have any luck, this site helped me loads!



    Quote: You dont stop playing in life because you’re getting old. You get old because you stop playing.

  8. Posted August 3, 2010 at 6:51 AM | Permalink

    DUDE !!!! You rule!

    The very key for working with wordpress under shared hosted iis6 and isapi rewrite is to use that line:

    RewriteRule ^(index\.php)*(.*)$ index.php/$2 [NC,L]

    That worked like a charm.

    Thanks a lot!

  9. jaydeep patel
    Posted September 3, 2011 at 2:28 PM | Permalink

    I have solved my problem with the help of your blog

  10. Chris
    Posted June 14, 2012 at 6:03 PM | Permalink

    If anyone is still using IIS6 and having this problem, in your ISAPI mod-rewrite under Engine Settings, check the box for Keep original “Host” header. I was getting 404 errors from IIS before making this change. After that the rewrite rules you gave worked great!

  11. Posted October 5, 2012 at 8:39 PM | Permalink

    i am not a developer, but got into a situation where i had to set up a windows server 2003 r2 with PHP, IIS6, and MySQL. I used the Helicon ISAP rewrite and all was going well…until i looked at it on IE. For whatever reason, I am getting a #? before my page url and the page wont fully load. On some pages, it just loads a youtube video in a lightbox.

    Not sure if you could throw me a suggestion as to a solution. This is working perfectly on a mac (safari/firefox), and chrome on a PC, just not on a pc IE or firefox.

    Permalinks set to custom structure: /%postname%/

    httpd.conf is set to:

    RewriteEngine on
    RewriteBase /pivotology/
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(index\.php)*(.*)$ index.php/$2 [NC,L]

    thanks for you time.

  12. Almeros
    Posted October 5, 2012 at 9:13 PM | Permalink

    Hi Mark, my first guess here should be this is a javascript issue. The hash is often used by js to represent some sort of state of the client. Do you use a js script which does some specific (workaround) tricks for IE?

    Also try to find someone who can help you side by side if you’re not a programmer. Will save you some headaches ;) .

3 Trackbacks

  1. By GoDaddy hosting – garbage! - Inane World on May 25, 2010 at 8:12 AM

    [...] [...]

  2. [...] [...]

  3. [...] wrote an article on my personal blog about fixing 404’s on WordPress Permalinks on an IIS 6.0 on a Windows webserver. There were two different sources I got the 404 from and which I had to fix; first from WordPress [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

  • Almeros’ Code Blog

    Welcome to Almeros' Code Blog at code.almeros.com. I'm a Software Engineer living in Groningen, The Netherlands.

    Too many times I found out some coding stuff I really want to share with you all; interesting new coding stuff, problems I found a solution for, things bothering me, etc.

    After many years of getting the knowledge and help from you (other blogging developers), it's time to give something back! That's why I started this blog. I hope you find it useful and that my posts save your day!