Latest TweetsWordPress and the Blank Target Vulnerability (aka rel noopener + noreferrer):… #WordPress #security #html
Perishable Press

htaccess Redirect to Maintenance Page

Redirecting visitors to a maintenance page or other temporary page is an essential tool to have in your tool belt. Using HTAccess, redirecting visitors to a temporary maintenance page is simple and effective. All you need to redirect your visitors is the following code placed in your site’s root HTAccess:

<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteCond %{REMOTE_ADDR} !^123\.456\.789\.000
 RewriteCond %{REQUEST_URI} !/maintenance.html$ [NC]
 RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif) [NC]
 RewriteRule .* /maintenance.html [R=302,L]

That is the official copy-&-paste goodness right there. Just grab, gulp and go. Of course, there are a few more details for those who may be unfamiliar with the process. Let’s look at all the gory details..

Redirecting Traffic with HTAccess

To redirect your visitors to a maintenance page, place the previous code into an HTAccess file located in your site’s root directory. This will ensure that all pages and resources contained within your domain will be redirected for visitors. Thus, if you would like to redirect only requests for a specific subdirectory within your domain, the .htaccess file containing these rules would be placed in that directory (instead of root).

Now that the HTAccess is in place, you’ll need to create and upload your maintenance page, named “maintenance.html”, to the root directory of your site. This file can be just about anything, and does not need to be written in HTML. You can use, say, PHP to make it all dynamic, but remember to change the two instances of the file name in the HTAccess code to match the actual name of your file.

Code Explanation

  1. The first line is merely a comment to explain the purpose of the code. It is not processed by the server.
  2. The second line enables Apache’s rewrite engine, mod_rewrite. Depending on your server setup, this line may be unnecessary.
  3. The third line checks to see if the request is coming from your computer. If it is, then the redirect does not happen. For this to work, you need to change the numbers in this line to match your own IP address.
  4. The fourth line prevents an infinite-loop scenario by testing the request against the name of your maintenance page. Obviously, we don’t want to redirect requests for the page to which we are redirecting.
  5. The fifth and final line contains the action. It basically redirects all requests that meet both of the previous rewrite conditions to the specified maintenance page. Apache doesn’t allow us to use 500-level response codes, so we are stuck with the next best thing, a 302 – temporary – response.

Update: Multiple IP Addresses

It was asked in the comments how this might work when you want to allow multiple IP addresses. There are basically two ways. First, you can add more RewriteConds to the previous code, like so:

<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteCond %{REMOTE_ADDR} !^123\.456\.789\.000
 RewriteCond %{REMOTE_ADDR} !^123\.456\.789\.000
 RewriteCond %{REMOTE_ADDR} !^123\.456\.789\.000
 RewriteCond %{REQUEST_URI} !/maintenance.html$ [NC]
 RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif) [NC]
 RewriteRule .* /maintenance.html [R=302,L]

With this method, edit each IP address to match your own, and add/remove as many IPs as needed. The second method is equally effective, and looks like this:

 Order Deny,Allow
 Deny from all
 Allow from 123.456.789.000
 Allow from 123.456.789.000
ErrorDocument 403 /maintenance.html
<Files maintenance.html>
 Order Allow,Deny
 Allow from all

This method is a bit simpler, but not as good for SEO should the search engines visit while in maintenance mode. The first method sends a 302 - Moved temporarily status code, while the second sends a less accurate 403 - Forbidden status code. Even so, should you go with method #2, edit the IPs to those of your own, adding or removing new lines as needed for site access.

It’s like a Pandora’s Box..

It’s difficult to keep posts short and sweet when working with HTAccess techniques. There is just so much that you can do with it. For example, we can do htaccess password-protection, allow access to multiple visitors, request specific redirects, and much more. But I refrained from complicating things in an effort to keep this post focused and on-topic. Nonetheless, there is always room for improvement, so if you see something that could make this simple HTAccess-redirect technique even better, then please share via the comments. Thanks!

Further reading

Jeff Starr
About the Author Jeff Starr = Fullstack Developer. Book Author. Teacher. Human Being.
60 responses
  1. You missed a sub-step in Step 3

    Where it says “123.456.789.000” – change those numbers to your IP address so you can still see your site.

  2. Stan Daniels May 19, 2010 @ 8:32 pm

    Just a tip: If you’re using images on your construction page, add this line in the .htaccess file.

    RewriteCond %{REQUEST_URI} !.(jpe?g|png|gif) [NC]

    Otherwise the images won’t load.

  3. Shouldn’t the redirect code be 503 and not 302? I was told that this will help if the search bots come along while your site is down for maintenance.

  4. Sorry I’ve just noticed what you’ve said about 500 level errors, the trick is to setup the 503 ErrorDocument to the file and then redirect all requests to 503

    ErrorDocument 503 /path/to/maintenance.html
    RewriteEngine On
    RewriteCond %{REMOTE_ADDR} !^111.222.333.444$
    RewriteRule .* - [R=503,L]

  5. The link that says, “allow access to multiple visitors” has a pop up that says, “Temporary Site Redirect for Visitors during Site Updates” – is it supposed to?

  6. Jeff Starr

    @Ewen: Thank you – I have updated the article with this information.

    @Stan Daniels: Definitely a good tip – thanks for pointing it out :)

    @Paul: Yes, that is an excellent technique. I want to keep this article focused, but I am planning a follow-up post that includes the custom error-document method along with more information on customizing for various specific scenarios, such as allowing for multiple IPs, different files, etc.

    @Josh At: Ah, you got me on that one! I honestly didn’t think anybody would notice. It was a bluff, so I will be updating the link after posting the follow-up article mentioned in my previous response (to Paul). Stay sharp!

  7. Has the same effect as creating a new index file, with the maintenance layout/text? Or it does more than that?

  8. Jack, it does more, since it redirects all visitors, those arriving at subpages, too. With a replaced index file, you’d only catch those arriving at the index page. Since loads of Google visitors arrive at subpages, this .htaccess solution is much better and it prevents overwriting something without you having an up to date backup.

  9. Jeff, I’ve learned a ton from lurking around your site for the last few years.

    One thing i’m having real trouble trying to figure out is this…

    i’m using a rewrite rule to rewrite a query string into a static looking url, eg:

    RewriteRule ^sanfrancisco/(.*)/(.*)\.php$ /sanfrancisco.php?&photo_id=$1&seo_title=$2/ [L]

    but what I want to do now seems complicated to me.

    I want to change the base file name to san-francisco so I’ve done that, and created the rewrite rule

    RewriteRule ^san-francisco/(.*)/(.*)\.php$ /san-francisco.php?&photo_id=$1&seo_title=$2/ [L]

    HOWEVER I still want to redirect anyone looking for to and when i implement a redirect like this…

    RewriteRule ^sanfrancisco.php$ /san-francisco.php [R=301,L]

    …i end up getting redirected, but the original query string gets appeneded to the end of the file, so instead of my url being redirected from


    it actually gets redirected to

    to try and make this succinct, how do i redirect htaccess rewritten friendly urls without having the query string get stuck back onto the url?

  10. Jeff Starr

    @Jason Wison: Try this:

    RewriteRule ^san-francisco/(.*)/(.*)\.php$ /san-francisco.php?&photo_id=$1&seo_title=$2/? [R=301]

    By adding the question mark at the end of the target URL, we are telling Apache to remove the query string. The [R=301] is optional, depending on your needs.

  11. Thank you, thank you, thank you. I was just talking about this the other day. I just knew there had to be an easier way to do this with renaming a bunch of pages which users could still get around if they had direct links to other pages.

    I was even trying “deny,allow” stuff. FABULOUS.

    You’ve saved me so much trouble. I’ll be keeping an eye on you now.


  12. Clearly, that should have read “without renaming a bunch of pages”. Typed too fast.

[ Comments are closed for this post ]