How to prevent direct file access in your wp-content directory

I was working on a secure site with sensitive video material that we needed strict members access to. Even though many plugins can make sure your direct permalinks can only be seen by logged in members, direct links to files in your wp-content directory are still accessible to others. They can even be hotlinked from other sites.

One way around this is to move the wp-content directory outside the web visible portion of your directory on the server, but even so WordPress can always link to such files. A better way is to tell your server not to give access to certain files (say ending with mp4 or mp3) and only allow access from your own domain.

We can use Apache Mod Rewrite for this – it’s a complex language that you can utilise in your .htaccess file within the wp-content folder.

Let me show you how to keep prying eyes out of your content.

The Problem

Say you had a PDF file that you’d like visitors on your own site to download.

However, if someone were to copy this link and call it from a browser window directly, or if they were to post the link to you PDF on another website then the document shall not be accessible. By default it is. Let’ fix that.

The Solution

Upload a .htaccess file into your wp-content folder. Have a look if one exists already, then append this code to the end of the file. If you don’t have one, just create a new blank file and add this code to it:

This rather strange sounding code is neither Linux nor PHP nor MySQL – it’s Apache (that’s the service which usually takes care of serving up those websites from a server). These are instructions that will tell Apache to do the following – I’ll explain this line by line:

  • here are some instructions I’d like you to use in this directory
  • IF someone comes from anywhere other than yourwebsite.com
  • AND they ask for a direct file that ends with any of the following (gif, png, jpg, etc)
  • AND they are not logged into WordPress on this domain
  • THEN direct every link to such files to http://yourwebsite.com

If these conditions are not met, then give out the file – everyone’s happy.

Why do I need this?

To prevent people hotlinking to your files. One aspect is security: say you have sensitive material that you only want your direct visitors to see. Or imagine you had a members area and give out a PDF that you’d like only logged in visitors to see without an encrypted link.

The same goes for image files or videos hosted on your site which you’d like to embed into your own pages but not allow embedding on external sites.

I had a guy once hotlink one of my images as his MySpace profile, the background graphic came from my server. If you’re on a plan with bandwidth limitations this can get you into trouble.

What else do I need?

Make sure you have an Apache web server running on your website, and that user overrides (i.e. .htaccess directives) are allowed.

When I wrote this article in 2012 this was a given, but since then the internet landscape has changed slightly. Nowadays, other web servers such as NGINX are commonplace, with which the above code will not work. Your web hosting company will be able to tell you more about your hosting environment.

Usage Examples

You can use this solution to conserve load and bandwidth on your server. For example, other users won’t be able to embed images hosted on your server in their websites (unless they upload them to their own), and sensitive files can only be shared on your own website.

However, this does not mean that sensitive files cannot be accessed at all; they are still available for download if visitors come via your website. Here’s an example of how to this solution works

  • you have a sensitive file at http://you.com/file.pdf
  • users coming from http://anywhere.com and click on that link will be redirected to your home page
  • users currently surfing http://whatever.com can paste your link into their browser bar will be redirected to your home page
  • users currently surfing your own website http://you.com can paste the link into their browser bar and will also be redirected to your home page, unless they are logged in to WordPress
  • if users are logged in to WordPress, and are currently surfing your website, and would paste the link to the file into their browser bar, they will get access

Alternatives

I’ve received many comments on this article over the years, with many suggested use cases and questions. It’s important to understand that while the above solution is a quick fix for preventing direct access sensitive files in certain cases, it is NOT a replacement for a full membership website.

If you’re selling anything downloadable and would like to make sure only authorised users have access to the files you provide, I suggest a membership plugin like WP eMember by Tips and Tricks HQ.

Further Reading

These articles discuss the same subject:

Jay is the CEO and founder of WP Hosting, a boutique style managed WordPress hosting and support service. He has been working with Plesk since version 9 and is a qualified Parallels Automation Professional. In his spare time he likes to develop iOS apps and WordPress plugins, or draw on tablet devices. He blogs about his coding journey at http://wpguru.co.uk and http://pinkstone.co.uk.

115 thoughts on “How to prevent direct file access in your wp-content directory

  1. Hi Jay, this is just what I needed and works fine, however, web browsers are now reporting non secure content and blocking images etc. Removing the htaccess file makes it secure again! Any Idea what can be happening?

    1. Hi Carl, no actually, that’s the first I’ve heard about it. I do know however that the new generation of browsers will report a non-secure website if the URL is a plain http rather than https. Since the last line of this ruleset creates a plain http re-write, perhaps it’s the reason for the browsers reporting an insecurity.

      Provided your website supports https and a certificate is installed properly, and WordPress is setup that way, you can try and create the .htaccess re-wrote so that it does a https instead of http in the last statement. Let me know what you find!

      1. Hey Jay, well it appears to solve it! Who’d have thought one bit of code would cause that! I changed to https on the top line too, just be doubly sure!

        I quite often get a non secure report if I don’t rebuild the cache after I have changed something in WordPress, and yes when I check the address it has changed from https to http. Not sure if that is a known thing or not, or what actually “decides” to drop the “s”, I am all very new to WP and website building in general. Thanks for your help, Carl.

  2. This solution worked beautifully for me, with one exception. My WordPress site sells online music lessons, which include mp3 and pdf files. I recently discovered that people could Google these files, connect directly to them, and download them. Gasp!

    Your .htaccess solution prevents people who are not logged in to the site from doing this, which is probably 99.9% of the threat. However, if someone is logged into the site (they can create a free account in a minute) they can still access these files directly, even if they haven’t purchased that music lesson.

    Is there anything I could do to prevent this?

    Important PS for others using this solution: I cut and pasted the code above into my .htaccess file, and discovered that all images on the site (photos, site logo, etc.) were blocked unless the user was logged in. Not good. I removed the jpg and png extensions from the exclusion list (along with some others) and everything went back to normal.

    1. Hi Dennis,

      That’s not something you can do with an Apache rewrite rule. The rewrite rule only tells the web server “if the requested file is requested from this domain, and if the user is logged into WordPress, then serve it. Otherwise, redirect”. It was originally designed to block sites hot linking to files on your server.

      What you need is a membership plugin. They’re usually quite complex to setup and often integrate with a shopping cart solution, making the setup even more complex. One such solution is the excellent WP eMember by Tips and Tricks HQ. I’m using it successfully over on my iOS Dev Diary. Feel free to test drive it there (I’ll give you a refund when you’re done of course).

      Alternatively, if such a solution is overkill, I’d recommend an external service such as Gumroad.com. You can upload files and sell them, and your users need to login with them to download content. It’s super simple to use and avoids the overhead of integration and configuration.

      Hope this helps, and all the best!

  3. Seems to work fine for all files EXCEPT xlsx?

    Works on xls files
    Works on xlsm files (added additional file type)

    But, when accessing xlsx – It is still prompting to download…

    1. You have to add appropriate MIME-type to the .htaccess-file bevor the code:
      AddType application/vnd.ms-word.document.macroEnabled.12 .docm
      AddType application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
      AddType application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
      AddType application/vnd.ms-powerpoint.template.macroEnabled.12 potm
      AddType application/vnd.openxmlformats-officedocument.presentationml.template potx
      AddType application/vnd.ms-powerpoint.addin.macroEnabled.12 ppam
      AddType application/vnd.ms-powerpoint.slideshow.macroEnabled.12 ppsm
      AddType application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
      AddType application/vnd.ms-powerpoint.presentation.macroEnabled.12 pptm
      AddType application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
      AddType application/vnd.ms-excel.addin.macroEnabled.12 xlam
      AddType application/vnd.ms-excel.sheet.binary.macroEnabled.12 xlsb
      AddType application/vnd.ms-excel.sheet.macroEnabled.12 xlsm
      AddType application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
      AddType application/vnd.ms-excel.template.macroEnabled.12 xltm
      AddType application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx

        1. Yeah… an addition to the main article: the .htaccess-file has to be in the wp-content/uploads folder! I guess if someone use year/month folders in each on has to be this file.

  4. Why is the rule based on the file extension? Should‘t it be the sub folder? I would never put a PDF if GIF in the wordpress root but rather in /downloads.

  5. Awesome! I would never leave here without dropping my comments.
    It worked perfectly like MAGIC! I have tried so many of this codes, but yours seems the only one that worked on my website.

    Actually, mine was for zip files so I moderated the code as shown below:

    RewriteEngine On
    RewriteCond %{HTTP_REFERER} !^http://(www\.)?yourwebsite\.com/ [NC]
    RewriteCond %{REQUEST_URI} !hotlink\.(zip) [NC]
    RewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in.*$ [NC]
    RewriteRule .*\.(zip)$ http://yourwebsite.com/ [NC]

    Thanks!

    1. Remember, the script works for everybody – including you! So for you to be able to download your own files, you must either be logged in, or use a link on your own website that links to those files.

      1. Thanks Though, Please how do i enable hotlink so people can download a file only from my website as when the direct download link to the files is been shared, it should redirect to the homepage of my website.

        E.g Say i have a file named file.zip located at the wp-contents/uploads, Now i created a post on my website, http://www.mydomain.com/file-download and i dropped a download link to this file there. I only want people to download the file directly from my website. If the direct link to the file (eg. http://www.mydomain.com/file-download.zip) is to be shared to someone else, it should redirect to the homepage of my website.. Hope You Understand what i mean?

        1. Hi Admin! You know, that is exactly what this code does. Anyone who would click on a hotlink to yourdomain.file-download.zip will be redirected to your front page and cannot download the file.

        2. @Jay Versluis: My Website dosen’t need someone to login before they can download on the website… What can i do now?

        3. From what you told me before, it sounded like this solution could work for you. But it has its limitations. If you’re serious about your file protection, look into a membership plugin (I’ve linked to one in the Alternatives section). There’s a big difference between the two approaches: this .htaccess solution is a quick and easy trick, but not 100% secure in all circumstances. A membership plugin is 100% secure, but comes with some additional setup and maintenance overheads – which might be overkill depending on your situation. Ultimately only you can decide what you need and what is important to you.

  6. Hello,
    great thanks for this article.
    Can you explain me why it doesn’t with samsung tablet default internet browser or web browser.
    The same page with your .thaccess file is ok on samsung with firefox or samsung but not with default internet browser or web browser with mp3 or mp4 : it say:
    Media error:Format not supported or source not found
    Download Filt: http://xxxxx/wp-contnet/uploads/2014//04/xxxx.mp4?_=2
    If I remove the .Htaccess file the same page with same mp4 and mp3 is readeok
    Why?
    Best regards

      1. Hi
        Thanks for the reply:
        In fact the prevent hotlinking works for pdf,jpg…but not for mp3 and mp4 on some browser:
        you can test it on safari on windows..If somebody has a solution…I’m here
        best regards

Add your voice!