Super Plugin Sale! Your Choice: BOGO or 30% Off »
Web Dev + WordPress + Security

Creating the Ultimate .htaccess Anti-Hotlinking Strategy

[ Image: Illustration of two hands holding a glowing object ] When I wrote my article, Stupid htaccess Tricks, a couple of years ago, hotlink-protection via htaccess was becoming very popular. Many webmasters and bloggers were getting tired of wasting bandwidth on hotlinked resources, and therefore turned to the power of htaccess to protect their content. At that time, there were only a couple of different hotlink-protection methods available on the internet, and the functional difference between them was virtually insignificant. All that was necessary for up-and-coming bloggers-slash-site-administrators to eliminate leaking bandwidth and stolen resources was a relatively straightforward copy-&-paste procedure. Implementing the de facto htaccess hotlink protection code required a simple binary decision: “do you want hotlink-protection or not?”

These days, however, things are not so simple. Today, if you do a search on the internet for “htaccess hotlink protection”, you’ll get the phone book. There are countless mutations of the once tried-and-true htaccess code. There have been significant improvements, but there is also plenty of noise and error lurking among the countless techniques. These days, protecting your site’s assets and conserving bandwidth requires either trusting the first htaccess trick you find, or performing a mind-numbing and time-consuming amount of research to find the htaccess anti-hotlinking strategy that’s perfect for you and your domain. With this article, I do the grunt work for you — analyzing, deconstructing, and cannibalizing a contemporary collection of hotlink-protection methods to create the ultimate htaccess Anti-Hotlinking Strategy.


Before we dig into the critical analysis of the myriad methods, let us continue our practice of catering to all of you copy-&-paste hounds out there by providing the finished product right up front:

# ultimate hotlink protection
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteCond %{HTTP_REFERER}     !^$
 RewriteCond %{REQUEST_FILENAME} -f
 RewriteCond %{REQUEST_FILENAME} \.(gif|jpe?g?|png)$           [NC]
 RewriteCond %{HTTP_REFERER}     !^https?://([^.]+\.)?domain\. [NC]
 RewriteRule \.(gif|jpe?g?|png)$                             - [F,NC,L]

Of course, there is much more to the story, as well as a small army of configurational options and possibilities. Nonetheless, if you could care less about the carefully executed logic and reasoning behind the development of this “ultimate” hotlink protection strategy, feel free to copy and paste the entire chunk into your site’s root htaccess file and remember to change the term “domain” to match that of your own. No other adjustments or edits are necessary. Strictly plug-n-play dude.

Now, for the intellectually inquisitive, or for those seeking a deeper understanding of the htaccess rules involved in hotlink protection, may I enthusiastically invite you to “read on”..

Digging in..

Okay, after much deliberation, I have decided to break this down as simply and concisely as possible. Thus, we will consider our collection of anti-hotlinking techniques individually and sequentially. For each method, we will examine the complete code, and then proceed with a brief analysis and summary of the technique’s key aspects. As we deconstruct each strategy, we will collect these gems and cannibalize the best of the best to create the finished product. Additionally, we will check out a few choice code variations and alternate configurational options that serve to expand overall functionality while facilitating a more flexible implementation. Here is a peak at the menu:

  • Hotlink Protection via Stupid htaccess Tricks
  • Hotlink Protection via REQUEST_FILENAME
  • Hotlink protection allowing all variations of the owner’s URL
  • Hotlink protection allowing for multiple domains
  • Streamlined, simplified hotlink protection
  • Code variations and configurational options
  • The ultimate htaccess hotlink-protection strategy
  • Conclusion (for reals this time)

Sound good? Okay, let’s begin..

Hotlink Protection via Stupid htaccess Tricks

In my article, Stupid htaccess Tricks, I present the following method of htaccess hotlink protection:

# hotlink protection via stupid htaccess tricks
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteCond %{HTTP_REFERER} !^$
 RewriteCond %{HTTP_REFERER} !^http://(www\.)?domain\.tld/.*$ [NC]
 RewriteRule .*\.(gif|jpg)$ http://www.domain.tld/eatme.jpe   [R,NC,L]

Back when I wrote the article, this basic hotlinking technique was widely employed and taken as the de facto standard method of preventing hotlinking scumbags. Although simplistic, there are several key aspects to this technique:

Error Prevention — The hotlink-protection rules are enclosed within an IfModule container that checks for the availability of the required Apache rewrite module (aka mod_rewrite) before attempting to process any Rewrite directives. This helps to avoid sudden, unwanted errors from crashing your site, and is just good practice in general.

Consolidated Canonicalization — As we will see, many other hotlink-protection methods use two RewriteCond rules for each targeted domain (either blocked or allowed) in order to accommodate for both the www and non-www versions of the site’s URL. Here, we have eliminated redundancy by considering either URL with a single line of code. We do this by preceding the domain with “(www\.)?”, which makes the www optional.

So, from this hotlink-protection ruleset, we will keep the error-preventing IfModule container and the consolidated canonicalization trick. The remainder of this technique is quite common, and will be repeated several times before this article has finished. Let’s move on..

Hotlink Protection via REQUEST_FILENAME

This method of hotlink protection takes a different approach by using the REQUEST_FILENAME parameter in the RewriteCond, thereby targeting the names of the hotlinked files rather than the referring domain:

# hotlink protection via request filename
RewriteEngine On
RewriteCond %{REQUEST_FILENAME}   -f
RewriteCond %{REQUEST_FILENAME}   -d
RewriteCond %{REQUEST_FILENAME}   \.(jpeg|jpg|gif|png)$         [NC]
RewriteCond %{HTTP_REFERER}       !^http://domain\.tld/.*$      [NC]
RewriteRule protected/(.*)        http://domain.tld/hotlink.jpg [R,NC,L]

This is another widely used technique that has been modified in countless ways. This version represents a generalized technique for protecting a specific directory (i.e., /protected/) from hotlink requests. Key aspects of this technique include the following:

Targets the file, not the referrer — Although I am not sure if it is more effective to target the requested file rather than the actual referrer, using REQUEST_FILENAME is known to be quite effective. In this particular example, all requests for .jpg, .jpeg, .gif, and .png images that are located in the “protected” directory will be blocked, unless from the owner’s domain (i.e., http://domain.tld/).

Checks for existence of requested file and directory — This is an added layer of protection that many hotlink protection methods use to further secure their server environment. In the second and third lines in our example, we are checking for the existence of the requested file (-f) and directory (-d). If the requested file and directory actually exist on the server, the remaining rules will be processed. If everything lines up, requests for protected file types will return the hotlink.jpg image; otherwise, the requested image does not exist and hotlink.jpg will not be served. This prevents the serving of your anti-hotlinking image in cases where the requested image does not exist, thus saving you bandwidth and avoiding confusion in general.

Beyond these two features — targeting the file and checking the file/directory— the remainder of this technique is rather common. In addition to these two gems, exclusively protecting a specific directory is also a handy trick. Let’s save these three items in our collective memory and continue with another example..

Hotlink protection allowing all variations of the owner’s URL

Another common implementation of hotlink protection allows image access only for all variations of the owner’s URL, including both www and non-www versions, as well as the IP address and port 80 access for the domain:

# hotlink protection allowing all source urls
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://domain.tld.*$            [NC]
RewriteCond %{HTTP_REFERER} !^http://www.domain.tld.*$        [NC]
RewriteCond %{HTTP_REFERER} !^http://domain.tld:80.*$         [NC]
RewriteCond %{HTTP_REFERER} !^http://www.domain.tld:80.*$     [NC]
RewriteCond %{HTTP_REFERER} !^*$       [NC]
RewriteCond %{HTTP_REFERER} !^*$    [NC]
RewriteRule .*[Jj][Pp][Gg]$|.*[Gg][Ii][Ff]$|.*[Pp][Nn][Gg]$ - [F,NC,L]

This common method incorporates two key aspects that we will cannibalize for our “ultimate” hotlink-protection strategy:

Comprehensive access for the source domain — This technique goes to great lengths to ensure that every possible version of the source domain is allowed open access to all images. Aside from blank referrer requests, all other domains and access attempts are stopped cold. It is unnecessary, however, to employ six lines of code to account for all instances of the host domain. Later in the article, when we integrate this aspect into our improved strategy, we will accomplish the same thing (and more) with only two lines of code.

Accounts for all variations of the target file extensions — The last line of this ruleset specifies which types of images to protect. In this case, we are protecting .jpg, .gif, and .png file types. Even better, we are preventing access via any variation of the file extension itself. File extensions written in uppercase, lowercase, or any combination thereof, are effectively blocked. This is a key aspect of any hotlink protection technique. Fortunately, however, the [NC] specified at the end of the last line makes it unnecessary to specify both uppercase and lowercase letters in each of the file names.

As mentioned, allowing comprehensive access is important, not only for the URL variations specified here, but for any required subdomains as well. Further, this code would benefit from the addition of logical [OR] operators combined with each of the first six [NC] operators. Without explicitly specifying “or” after each line, the conditions are processed with an inherent “and”, meaning that all conditions must apply before the rewrite occurs.

Hotlink protection allowing for multiple domains

In this example, we demonstrate a widely used technique for allowing image access to multiple domains, including Yahoo!, Google, and three additional domains:

# hotlink protection allowing for multiple domains
RewriteEngine on
RewriteCond %{HTTP_REFERER}  .
RewriteCond %{HTTP_REFERER}  !^http://([^.]+\.)?domain-01\. [NC]
RewriteCond %{HTTP_REFERER}  !^http://([^.]+\.)?domain-02\. [NC]
RewriteCond %{HTTP_REFERER}  !^http://([^.]+\.)?domain-03\. [NC]
RewriteCond %{HTTP_REFERER}  !search\?q=cache               [NC]
RewriteCond %{HTTP_REFERER}  !google\.                      [NC]
RewriteCond %{HTTP_REFERER}  !yahoo\.                       [NC]
RewriteCond %{REQUEST_URI}   !^/hotlink\.jpg$               [NC]
RewriteRule \.(gif|jpg|png)$ http://domain.tld/hotlink.jpg  [R,NC,L]

This very useful method enables us to specify additional domains for which to allow image/resource access. There are many situations in which webmasters need to extend access to search engines, feed readers, and associate sites. Here are the key points of this method:

Better “blank-referrer” access — Every serious hotlink protection strategy provides resource access for “blank-referrer” (or “no-referrer”) requests. Blank referrers are commonly associated with third-party ISPs, firewalls, direct requests, and other such situations. Unless you have specific reason to do otherwise, it is highly recommended that you enable access to blank-referrer requests. As seen in previous examples, this is accomplished via “!^$”, which means “not blank.” This example employs the more semantically correct “ . ” (dot), which specifies any character, including …

Comprehensive access for multiple domains, subdomains — Following the pattern presented in the first three lines, we may allow access to as many domains as necessary. Even better, all subdomains associated with the allowed domains are also included via the regex, ([^.]+\.)?, which literally matches virtually any string preceding the domain. Thus, all subdomains are also allowed access.

Access for Google, Yahoo!, et al — Allowing access to the major search engines is a great way to attract new visitors to your site. Of course, there are many possibilities here, depending on your personal site-optimization strategy.

Allow universal access to the hotlink.jpg image — If you are serving a nasty image to the worms that would otherwise steal your bandwidth, it is important that they are able to access it. Many of the hotlink-protection strategies I have seen around the Web somehow fail to accommodate or mention this important aspect. Fortunately, this example reminds us of the fact by allowing complete access to our offensive anti-hotlinking image.

Wow, that’s a lot of useful material from this technique. Let’s add it to our stash and move on..

Streamlined, simplified hotlink protection

In our final example of htaccess hotlink-protection techniques, we examine an effective, streamlined approach:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://([a-z0-9]+\.)?domain\.tld [NC]
RewriteRule \.(gif|jpe?g|png)$ - [F,NC,L]

Although simple, this method provides two key aspects:

Alternate wildcard regex wildcard string for subdomains — In our previous example, we enable access to all subdomains associated with our allowed domains via regular expression. This method accomplishes the same functionality, only by using an alternate regex statement. Both are effective, but it is good to have an alternative ;)

Condensed file extension list — This example demonstrates a way to consolidate and simplify the list of protected file types by using employing a “?” (i.e., question mark) to signify an optional letter “e” for the .jp(e)g extension. Here, the question mark indicates that the preceding character (the letter “e” in this case) is optional, thereby producing a match for either scenario. This is a useful trick that will serve us well in our final strategy.

Now that we have pillaged a fine collection of contemporary htaccess anti-hotlinking rules, let’s shift gears momentarily and consider several individual htaccess directives involved with hotlink prevention. Many of the following rules are alternate versions of previously considered code.

Code variations and configurational options

Let’s face it, there are often many ways to formulate htaccess directives, especially when it comes to using Apache’s mod_rewrite to prevent hotlinking. Here are a few examples demonstrating variations of previous code examples..

Optimizing the file type list

In our third anti-hotlink example, the following code is used to specify the protected file types:

RewriteRule .*[Jj][Pp][Gg]$|.*[Gg][Ii][Ff]$|.*[Pp][Nn][Gg]$ - [F,NC,L]

That works, but we can simplify it a bit:

RewriteRule \.([Jj][Pp][Gg]|[Gg][Ii][Ff]|[Pp][Nn][Gg])$ - [F,NC,L]

Okay, that’s a little better, but there is still room for improvement. Notice the NC in the brackets. That tells Apache to ignore the casing of characters in the regex string. Thus, explicitly specifying both uppercase and lowercase characters in the list of file types is unnecessary. This fact enables us to simplify the RewriteRule quite significantly:

RewriteRule \.(jpg|gif|png)$ - [F,NC,L]

There, that’s much better — but we can improve it a little bit more by supporting all three types of .jpg files (i.e., .jpg, .jpeg, and .jpe), in addition to .gif and .png files:

RewriteRule \.(jpe?g?|gif|png)$ - [F,NC,L]

Of course, to protect additional file types, simply add another pipe symbol (“|”) followed by the associated file extension. For example, to add several additional file types, we could write something like this:

RewriteRule \.(jpe?g?|gif|png|bmp|tiff?|pic)$ - [F,NC,L]

And yes, we can easily support other, non-image resources files as well. Let’s protect some multimedia files and Microsoft documents:

RewriteRule \.(jpe?g?|gif|png|bmp|tiff?|pic|mp3|doc|xls)$ - [F,NC,L]

Different responses to hotlink requests

In most of the anti-hotlinking rules presented above, the server responds to all blocked resource requests with a “403 – Forbidden” error. This works well enough, but there are many situations where a simple 403 just doesn’t cut the mustard. For example, if you utterly despise hotlinking bandwidth thieves, you may prefer to serve ‘em a piping-hot close-up of your favorite hairy hole (or whatever). To do this, modify the last line in your set of rules as follows:

# serve em a macro shot of your hairy hole
RewriteRule \.(jpe?g?|gif|png)$ http://www.domain.tld/hairy-hole.jpg

Now, when you do this, you want to ensure that you are not blocking access to your hairy-hole.jpg by including a line similar to this directly before the RewriteRule:

# ensure access to your hairy hole jpg
RewriteCond %{REQUEST_URI} !^/hairy-hole\.jpg$ [NC]

Likewise, rather a macro-shot of your nose hole (or ear hole, for that matter), you may want to refer hotlinking scum to a specific file, say “hotlink-policy.html”. In this case, modify the last line in your set of rules as follows:

# send em a web page explaining your hotlink policy
RewriteRule \.(gif|jpe?g|png)$ http://www.domain.tld/hotlink-policy.html

Finally, if you are concerned that your server will not process the RewriteRule correctly unless the requested file type happens to match that of your hairy hole image, you will need to prepare a version of your hairy-hole image in each of the protected file formats.

For example, if you are protecting .jpg, gif, and png file types, and would like to serve hotlinkers a copy of your hairy hole, you will need to prepare a version of the image in each of the three file formats (e.g., hairy-hole.jpg, hairy-hole.gif, and hairy-hole.png). Then, to summon the matching file type when hotlinking is detected, replace the last line in your ruleset as follows:

# serve em a copy of your hairy hole with a matching file type
RewriteRule \.(jpg|gif|png)$ http://domain.tld/hairy-hole.$1 [F,NC,L]

As described, this directive matches the requested file type with a similarly formatted copy of your hairy hole. You know the one. Now, let’s take a look at a complete example using this technique:

# serve hotlinkers a macro shot of your hairy hole
RewriteEngine on
RewriteCond %{HTTP_REFERER}  !^$
RewriteCond %{HTTP_REFERER}  !^http://([a-z0-9]+\.)?domain\.tld [NC]
RewriteCond %{REQUEST_URI}   !^/hairy-hole\.                    [NC]
RewriteRule \.(jpg|gif|png)$ http://domain.tld/hairy-hole.$1    [F,NC,L]

Let’s move on..

Serve ‘em a nice 404 page

A great way to confuse content thieves is to respond to their hotlink requests with an artificial 404 page. To do this, add the following code to htaccess:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://([a-z0-9]+\.)?domain\.tld      [NC]
RewriteRule ^(.*)\.(gif|jpg|png)$ http://domain.tld/404.php?$1.$2   [NC,L]

..and then place a file called 404.php in the site root (or directory of your choice, just change the htaccess RewriteRule to match the new location). Within the blank 404.php document, copy & paste the following:

<?php header("HTTP/1.0 404 Not Found"); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
<html xmlns="">
<head><title>404 Not Found</title></head>
<body><h1>404 Not Found</h1>
<p>The requested URL /<?php if ($_SERVER['QUERY_STRING']) : echo $_SERVER['QUERY_STRING']; endif; ?> was not found on this server.</p>
<p>Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.</p>

Protect resources on secure domains

As we wrap up the odds and ends, let’s take a look at a simple tweak that will expand hotlink protection to target resources on secure (https://) domain. To achieve this, simply add a “s?” (optional “s” character) after the http portion of the HTTP_REFERER string that represents the site in question. Here is an example:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://([a-z0-9]+\.)?domain\.tld [NC]
RewriteRule \.(gif|jpe?g|png)$ - [F,NC,L]

At last, the ultimate htaccess hotlink-protection strategy

Now that we have deconstructed a plethora of htaccess hotlink-protection directives, it’s time to throw down the “ultimate” htaccess hotlink-protection strategy. Rather than present a convoluted, one-size-fits-all chunk of heavily commented htaccess code, I provide two different versions, one requiring minimal editing, and another packed with everything:

  • Complete site protection — complete protection, minimal editing.
  • Comprehensive protection — allow multiple sites, your IP, and more.

Version 1) Complete Hotlink Protection

If you are looking for complete hotlink protection for your site and all subdomains, copy & paste the following code into your site’s root htaccess file:

# ultimate hotlink protection
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteCond %{HTTP_REFERER}     !^$
 RewriteCond %{REQUEST_FILENAME} -f
 RewriteCond %{REQUEST_FILENAME} \.(gif|jpe?g?|png)$           [NC]
 RewriteCond %{HTTP_REFERER}     !^https?://([^.]+\.)?domain\. [NC]
 RewriteRule \.(gif|jpe?g?|png)$                             - [F,NC,L]

To use the previous code, only one edit is required: change the term “domain” to match your domain. For example, if your domain name is, you would replace “domain” with “website”. Note that this code is set to protect the following file types: .jpg, .jpeg, .jpe, gif, and png. To protect additional files, such as those with the .ico format, simply add “|ico” after the “|png” in both the 6th and 8th lines.

Version 2) Comprehensive Hotlink Protection

For those of you desiring a more robust, flexible solution for hotlink protection, the following code encompasses the entire spectrum of functionality. In order to accommodate multiple features, certain lines of code have been temporarily disabled via comments (i.e., pound signs #). Further, comments are included throughout the code to explain the various options. Having said that, grab a copy, read through the code, and edit to taste:

# ultimate hotlink protection #

# disable directory browsing
# uncomment this option to protect access to directories
# Options -Indexes

# enable the following of symlinks
# uncomment this option if hotlink protection fails to work
# Options +FollowSymLinks

# verify presence of mod rewrite
<IfModule mod_rewrite.c>

 # enable the rewrite engine
 RewriteEngine on

 # check that file exists
 RewriteCond %{REQUEST_FILENAME} -f

 # check for requested file types
 # include additional file types here
 RewriteCond %{REQUEST_FILENAME} \.(gif|jpe?g?|png)$                [NC]

 # allow blank referrer requests
 RewriteCond %{HTTP_REFERER}     !^$

 # allow all requests from your domain
 # edit the domain to match your own
 RewriteCond %{HTTP_REFERER}     !^https?://([^.]+\.)?domain\.      [NC]

 # allow all requests from your ip address
 # edit the ip address to match your own
 RewriteCond %{HTTP_REFERER}     !^https?://123\.123\.123\.123(.*)$ [NC]

 # additional site access
 # include additional sites here replace domain names and or 
 # remove unnecessary lines or add new lines for more sites
 RewriteCond %{HTTP_REFERER}     !^https?://([^.]+\.)?domain_01\.   [NC]
 RewriteCond %{HTTP_REFERER}     !^https?://([^.]+\.)?domain_02\.   [NC]
 RewriteCond %{HTTP_REFERER}     !^https?://([^.]+\.)?domain_03\.   [NC]

 # search engine access
 # include or remove search engines feed readers and other sites
 RewriteCond %{HTTP_REFERER}     !search\?q=cache                   [NC]
 RewriteCond %{HTTP_REFERER}     !google\.                          [NC]
 RewriteCond %{HTTP_REFERER}     !yahoo\.                           [NC]

 # allow access to all requests for your anti hotlink image
 # to serve an image instead of delivering a 403 error
 # uncomment the next line and edit the path and file name
 # RewriteCond %{REQUEST_URI}    !^/hotlink\.jpg$                   [NC]

 # deliver the hotlink image for all requests for the listed files
 # protect additional file types by editing the list below
 # if you are serving a file instead of a 403 
 # uncomment the next line and edit the path and file name
 # RewriteRule \.(gif|jpe?g?|png)$ http://domain.tld/hotlink.jpg    [R,NC,L]

 # return a 403 error when any of the following file types is requested
 # you can protect additional file types by editing the list below
 RewriteRule \.(gif|jpe?g?|png)$                                  - [F,NC,L]

# close the module container

Essentially, both of these hotlink-prevention methods are the same, employing the same underlying htaccess rules. The first version provides the fundamental functionality required to completely protect any domain, and is a generalized version intended for everyday, plug-n-play usage. The second version provides the same comprehensive coverage while also facilitating flexible customization and configuration via strategically implemented code comments.

Wrapping up then, a huge “thank you” goes out to everyone who contributed to the myriad anti-hotlink techniques discussed in this article. And, as is always the case with code presented here at Perishable Press, if you know of any way to improve any of the code examples, please drop a comment or contact me directly. Thanks ;)

Conclusion (for reals this time)

I hope this article has shed some light on the various aspects of hotlink protection via htaccess. Hopefully, the code examples presented here will help beginners gain a clearer understanding of how hotlink prevention works, while reminding a few of the Rewrite veterans in our audience of some of the subtleties associated with mod_rewrite and the process of preventing access to target resources. At the very least, I hope that the “ultimate” htaccess hotlink-protection strategy developed in this article provides webmasters with more control over their resources, images and otherwise. … God bless! ;)


About the Author
Jeff Starr = Web Developer. Security Specialist. WordPress Buff.
The Tao of WordPress: Master the art of WordPress.

75 responses to “Creating the Ultimate .htaccess Anti-Hotlinking Strategy”

  1. I haven’t had much of a problem with hotlinking on the sites I work with, but they don’t have many graphics worth stealing. When I do come across one in the logs usually I just rename the picture on the server and replace it with another picture. If the new file is 3000px by 3000px and breaks the layout of their site, even better :)

    I supposed a better way for me to handle it would be to just stick our URL in the bottom corner of the image and try and drive some traffic to us through it

  2. I’d like to share my recent experience with this hotlink protection:

    I removed this anti-hotlinking strategy from my blog when I discovered recently that it was blocking me from giving friendly links in blog discussions.

    I sometime host files directly on my blog, and hotlink to them to underline some points when discuting on blogs. Last in date, I wanted to show my blog loading time performance, so I uploaded the file, and linked to this URL.

    Some time after I posted the comment, I received a mail from the blog author saying that my link was acting strangely: on the first click, it was giving a 404 error, then when the page was reloaded, it displayed the image just fine.

    After some reflexion, I find out that the great hotlink protection given here was responsible for this trouble. I removed it because I don’t have much abuses of my images, so it was more a principle action and as such, it was quite optional.

  3. @Varney: good point, and something that I have contemplated for this site as well. I mean really, the images I post on this site are few and far between, and certainly aren’t anything that most people are clamoring over (e.g., bikini models, sports cars, and celebrity shots). I guess it’s a trade-off between a little bit of stolen bandwidth and the amount of server resources required to parse the htaccess directives on every page load. Frankly, I am seriously considering removing the anti-hotlinking rules for this site and a few others as well. We’ll see how it goes..

  4. @Louis: Are you saying that one of the hotlink methods provided in this article doesn’t work properly? Do you still have a copy of the exact code you were using? I would like to look at it, especially if there is a potential issue with the method. This technique is used by a number of people and this is the first I have heard of something not working correctly.

  5. Hi Jeff,

    I don’t think that the protection code hasn’t worked well. The problem is in its principle itself: it blocks image visualization for images that aren’t loaded directly from the site official URL.

    I block abuses of your own images on other sites, but it also prevent you from hotlinking your own images to friends – i.e., storing images on your website data space and then giving direct link while having conversations on blogs for example.

  6. Jeff Starr 2008/11/09 9:55 am

    @Louis: Ah, I see what you mean. Yes, you are correct, these anti-hotlinking methods are designed to prevent hotlinking images from any source other than the original domain. Glad to hear that everything is working as expected! :)

  7. how to protect files .js or .css from save page as in all browser? that possible using .htaccess ?

  8. Jeff Starr 2008/11/16 9:20 pm

    @martin: I think it’s possible — I have seen it done on a website once — but I do not know how they did it..

  9. dora the explorer 2009/01/25 5:24 pm

    Okay, here is my question. Am I a n00b or a dunce? You choose.

    A url redirect as a solution for unauthorized hotlinking. Does that make sense? Take the url of the image that is being linked to, change that url to redirect to your original website page from where the hotlink is stolen from. Am I missing something here? I’m scratching me head a bit. I can’t find any other mention of this. Does Google punish sites for doing such a redirect? I mean, I’m just trying to deal with the theif.

  10. @dora the explorer: Great idea. I use that trick here at Perishable Press all the time. Google does not punish this sort of behavior, as far as I know. Your site and its contents are yours — you are free to redirect anything as you wish. If someone is lame enough to steal your stuff, by all means, do whatever is necessary to send a clear message.

  11. Jeff,

    I have thousands of munchkins coming in accessing just swf files and nothing else, the referrer is blank, would taking out the

    RewriteCond %{HTTP_REFERER} !^$

    solve my problem.

    Before I was merrily adding hotlinked referring sites to a list (400 lines at the moment) like so

    RewriteCond %{HTTP_REFERER} xxx\.com [NC,OR]
    RewriteCond %{HTTP_REFERER} xxxxx\.net [NC,OR]
    RewriteCond %{HTTP_REFERER} xxxx\.net [NC,OR]
    RewriteCond %{HTTP_REFERER} xxxx\.org [NC,OR]
    RewriteCond %{HTTP_REFERER} xxxxx\.org\.uk [NC,OR]
    RewriteCond %{HTTP_REFERER} xxxx\.be [NC,OR]
    RewriteCond %{HTTP_REFERER} joemonster\.org [NC]
    RewriteRule \.(swf)$ redirect.swf [NC,L]

    but now with all these people showing no referrers i’m stumped.


  12. hmm

    I couldn’t get this to work when allowing my ip address

    RewriteCond %{HTTP_REFERER} !^https?://123\.123\.123\.123(.*)$ [NC]

    but when i changed to this

    RewriteCond %{REMOTE_ADDR} !^123\.123\.123\.123$ [NC]

    it worked but broke hotlinking.

    any ideas?


Comments are closed for this post. Something to add? Let me know.
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
Blackhole Pro: Trap bad bots in a virtual black hole.
All free plugins updated and ready for WordPress 6.6 dropping next week. Pro plugin updates in the works :)
99% of video thumbnail/previews are pure cringe. Goofy faces = Clickbait.
Crazy that we’re almost halfway thru 2024.
I live right next door to the absolute loudest car in town. And the owner loves to drive it.
8G Firewall now out of beta testing, ready for use on production sites.
It's all about that ad revenue baby.
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.