How to prevent hotlinking with htaccess in WordPress and why most common use about it doesn’t work?

I started with this .htaccess configuration:

Options -Indexes
<files wp-config.php>
order allow,deny
deny from all
</files>

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
RewriteRule ^(.*\.php)$ $1 [L]
RewriteRule . index.php [L]

# END WordPress

and to protect the website from theft with hotlinking, I searched the best solution adding this code on the bottom of the code:

RewriteEngine on
RewriteCond %{REQUEST_URI} !hotlinking\.png$
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?mywebsite\.com [NC]
RewriteRule \.(jpe?g|png|gif)$ /hotlinking.png [NC,L]

The code above is the most common solution to prevent hotlinking, it’s very clear, but it doesn’t work: when I paste the URL of image, for example

https://www.mywebsite.com/wp-content/uploads/sites/2/2018/01/imagexample.jpg

the browser shows the image.

Is there an error on the code or is there a better solution?

1 Answer
1

when I paste the URL of image

I assume you mean when you paste the URL directly into the browser’s address bar, as I can’t think you’d be pasting it anywhere else. (?)

If that is the case then the behaviour you are seeing is correct – the browser should show the image. This isn’t really “hotlinking”, this is a direct request. You can’t realistically block direct requests (when the HTTP Referer is empty) as you could end up blocking these images for real users of your site that don’t send the HTTP Referer header as part of the request.

The following condition is what allows this request to happen:

RewriteCond %{HTTP_REFERER} !^$

ie. When the HTTP_REFERER is not empty.


ASIDE: You’ve tagged your question “multisite”, however, you appear to have both sets of code in your .htaccess file: standard single-site and multi-site? The single-site code is first, so this is what’s “winning”.

Leave a Comment