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. Oh come on, Dave – if you can’t figure that part out, then you really shouldn’t be using this code at all!

        2. Yes, I think it’s pretty obvious. The trick is this: leave everything as it is, every slash, every scary character, and ONLY replace the URL to your website. For example, if your actual website’s URL is http://www.obvious.com, then the whole block should look like this:

          Note that you have to change the URL in two places in the block, as shown. Also, if you only want to block PDFs, shorten the list of file extensions (like I did here).

  1. My only issue is it’s not redirecting to the page I set, just a 404. It’s not the page that’s 404ing but the file, which is cool enough and works much better than before. I just decided to look into this now, but I had previously assumed that a security plugin had this direct access block thing, hah. Oh well, it works so well, now. Thank you.

  2. Hey it worked perfect. But I have another case

    I have Mr.A having access to files ABC
    I have Mr.B having access too files XYZ

    But the above code will treat them as same – means registered users and they can swap my member only confidential files!

    How to kill this?

  3. We are using essentially the same;
    RewriteCond %{REQUEST_URI} .*[ProtectedFolder].*
    RewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in.*$ [NC]
    RewriteRule . /my-account [R,L]

    and it is working perfectly, except for one scenario;
    Video files(mp4) do not play on iOS devices. “Error loading this resource”.

    There does not seem to be any encoding file issues as when I remove the above lines from the htaccess the videos play without issue on iOS devices.

    I have found quite a few posts about the issue from over the preceding years, but none seem to have had a working solution to this issue =(
    I was hoping that you may have some insight?

    1. Well interestingly, it seems that iOS is just fussier with cookies than Android and Desktops when using WP cookies with htaccess to protect folder content.
      Using the “Remember Me” option when logging into WP sites prevents the “Error loading this resource” error message and the videos play fine.

  4. Thank you for this post Jay !
    I looked everywhere to find a simple and working solution to this problem.
    Your easy to understand and easy to implement code lines solved my problem.
    Just adding these lines to the already existing .htaccess and adjusting the website url did the trick.

  5. This didn’t work for me. Uploaded the .htaccess to the wp-content folder then went to my website, logged out then entered a url direct to a pdf file in the browser and it opened just fine. Is there some caching going on or is it possible my web server is not using Apache?

    1. Hi Andy, both of these scenarios are indeed possible. Let’s check one after the other.

      I’d test setups like this with two different web browsers, one in which you’re logged in, and another one in which you’re not (say Chrome and Firefox). Therefore you can make a change and see how the non-logged in browser is affected by it. Using the same browser may indeed give you caching issues and false results.

      To test if your server is running Apache or NGINX, open Terminal or a Command line tool of your choice, then type

      Replace yourdomain.com with your actual domain or your server’s IP address. Now we’ll make a simple http request and read the results:

      Only type the first line, the rest will be the output of the telnet tool. In this case, it looks like the server is running NGINX. In reality it’s more complex than that though: on my Plesk machine, there’s a very elaborate setup that first processes PHP via Apache, and then serves those files via NGINX. So although the telnet tool is right in saying the file is served by NGINX, it is processed by Apache beforehand.

      Here’s what an Apache web server might print out:

      Best ask your hosting provider which web server they’re using on your site. Hope this helps!

Add your voice!