Update 2012/07/15 all code updated with the new .htaccess rules (changed in WP 3.0). The code in this article should work with all versions of WordPress. </update>
I recently performed a series of tests on a fresh installation of WordPress 2.8.6 to determine the exact htaccess rewrite rules that WordPress writes to its htaccess file for various permalink configurations. Under the WP admin option menu, WordPress lists four choices for permalink structure:
- Default:
http://perishablepress.com/press/?=123 - Date and name based:
http://perishablepress.com/press/index.php/2006/06/14/sample-post/ - Numeric:
http://perishablepress.com/press/index.php/archives/123 - Custom:
/%year%/%monthnum%/%day%/%postname%/
The "default" option is to not use permalinks. The "date and name based" setting invokes the /index.php/%year%/%monthnum%/%day%/%postname%/ rule pattern. The "numeric" setting invokes the /index.php/archives/%post_id% rule pattern. And the "custom" setting invokes whatever pattern is specifically chosen. For our "custom" option, we chose the /%category%/%author%/%postname%/ pattern.
For the test, we began with the common "date and name based" permalink configuration. Then, after invoking the chosen permalink structure, the htaccess file was downloaded and the new WP rules were recorded. After this, the admin permalink settings were switched back to the "default" configuration. Finally, we deleted the new rules and uploaded the htaccess file. This process was diligently repeated for each different permalink configuration. It should also be noted that blog performance was checked during each round of testing.
The results indicate conclusively that WordPress uses the exact same set of htaccess rules for all permalink configurations. Surely this information is available elsewhere on the internet, however we were experiencing several inconsistencies related to permalink structure that inspired us to determine for ourselves the precise htaccess rules for WordPress permalinks.
Without further ado, the htaccess rules for all WordPress permalinks1 are precisely either #1 or #2:
[ #1 ] If WordPress installed in the root directory »
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
[ #2 ] If WordPress installed in a subdirectory called "foo" »
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /foo/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /foo/index.php [L]
</IfModule>
# END WordPress
1 Note: These results are valid for standard permalink structures invoked via a standard WordPress install and may not operate effectively for non-standard or highly specialized configurations. We assume that if you are hard at work hacking and tweaking, you must know what you are doing.
96 Responses
Laurent – September 17, 2008
Thanks Jeff! I look forward to the solution. :)
Anyway awesome site you have here, lots of technical info that I wouldn’t find anywhere else. You got one more loyal reader to your site. Thanks.
Chetz – September 22, 2008
Hi I had an Internal Server Error when I edited or add the .htaccess on my wordpress directory. I found out a solution from the Internet. Add the following on the first line of your .htaccess file..
Options +FollowSymLinksThat works for me.
Chetz Yusof
Jeff Starr – September 24, 2008
Yes symbolic links must be enabled on your server in order for the rewrite rules to take effect. In my experience, most servers have this option enabled by default, but some do not. Overriding the default setting via htaccess as you have done here is a sound solution. Another good idea is to wrap the WordPress rewrite rules in an
IfModulecontainer to check for the presence of the required functionality. In any case, thanks for sharing, Chetz — much appreciated!Chetz – September 24, 2008
You’re most welcome Jeff! I know how frustrating it is to figure out something you don’t know anything about. So, I hope by sharing this info. it’ll help someone.
Silver – October 2, 2008
Thank you so much for the information.
I used your code for WP install in root above verbatim.
i have my permalinks set to: /%postname%/
My question Is, why do links to pages that are not assigned a page parent (main nav items) not work; however, pages that are assigned to that page parent previously listed do display?
In other words:
Not working – ./about/
Working – ./about/test2/
thank you in advance for your response.
Silver
Jeff Starr – October 5, 2008
Hi Silver, I am not sure what the issue could be, but you may want to try resetting your permalinks and then re-creating them. Reset them back to WordPress defaults and then delete the WordPress htaccess rules from your htaccess file. Then surf around on your site for awhile to ensure that each of the different types of pages are loading correctly (via the default URL structure). If everything looks good, try enabling your desired permalink format and then replacing the htaccess rules provided in this article, which should be the same as the ones generated by the WordPress admin panel, btw. Hopefully, that will do the trick; but if not, there may other issues involved. I hope that helps!
g1smd – October 6, 2008
Those .htaccess rules do not fix non-www and www duplicate content issues.
That is a vital thing to add to the mix.
Jeff Starr – October 6, 2008
@g1smd: You are correct! This article focuses on the htaccess rules for all WordPress permalinks (as the title suggests). I deal with WordPress canonicalization issues separately in other articles. Here are two of my finest efforts, but there are certainly others available via the “Related articles” section at the end of each post.
Comprehensive HTAccess Canonicalization for WordPress.
htaccess Combo Pack: WordPress Permalinks and non-www Redirect
I hope that helps! Cheers!
Paul – October 9, 2008
Holy crap, you just saved my A$$! Thank you!
Mark – October 31, 2008
I have been trying to figure this pretty permalink thing out with no success. I implemented your #2 solution. The IT guys installed the mod_rewrite.so instead of mod_rewrite.c. Should this make any difference? I’m pretty new to .htaccess thing.
Jeff Starr – November 2, 2008
Hi Mark, I am not sure what the issue could be, but a search on Google reveals quite a few questions/concerns about
mod_rewrite.so-related issues. I would recommend speaking directly with your IT people; there are many things that they could have done to affect Apache’s rewrite functionality.Laurent – November 10, 2008
Hi all, regarding my comment #71 I have found the problem. It was a case-sensitive problem. One of my files had an uppercase first letter and once I change it to lowercase through ftp, it worked perfectly. Does htaccess rules look at case sensitivity? A bit confused here…