This tutorial shows how to require user login to access any files stored in the WordPress Media Library. So for example, let’s say that you have a bunch of images uploaded via the Media Library. And you want to protect those images, videos or PDFs, so that they are not accessible to the general public. The user must log in to access any media files. Once the user is logged in, then they will have full access to all files. This technique is useful for any site where you want to require login to access content. The technique described in this article uses cookies to determine if the user should have access to uploaded/media files. So it works great for like 99.999% of users. A determined attacker, however, could bypass this method and access your media files. If you need something that is 100% bullet-proof and secure, check out the "hard way" folder within this parent folder: it requires a bit more setup/configuration, but is well-tested and works great (but only redirects to the WordPress Admin login, despite Kevin working hard to change this, which may not be what you want.) NOTE: THIS PROBABLY ONLY WORKS ON APACHE SERVERS (SEARCH IN GOOGLE FOR "DENY DIRECT ACCESS TO WORDPRESS MEDIA FILES FOR NGINX SERVERS") First create a new .htaccess file inside of the /wp-content/uploads/ directory. Inside of the new .htaccess file, add the following code: # require login for media files # more info: https://m0n.co/11 RewriteCond %{REQUEST_FILENAME} (.*) RewriteCond %{REQUEST_FILENAME} \.(pdf)$ [NC] //replace above line with this to check if just pdf is being requested RewriteCond %{REQUEST_FILENAME} \.(pdf|zip|mp4|ogv|webm)$ [NC] //..or if you need more file types, use this line instead of above RewriteCond %{HTTP_COOKIE} !wordpress_logged_in_([a-zA-Z0-9_]*) [NC] RewriteRule .* - [F,L] //standard 403 forbidden response RewriteRule (.*) https://example.com/wp-login.php [R=302,L] //replace "standard 403" response with any URL (here a login URL) and a temporary redirect (302) NOTE: BE SURE TO PUT THIS OUTISIDE ANY DYNAMIC HTAACCESS RULES WORDPRESS AUTOMTAICLLY CREATES OR IT WILL BE OVERWRITTEN. THERE CAN BE 2 CHECKS IN ONE HTACCESS FILE. No editing is required. Once that code is in place, upload to the server and done. How does the above code technique work? First notice the opening and closing containers. That checks for the required Apache module, mod_rewrite, before attempting to execute any contained rules. Then it: 1. Checks if the request is for any file 2. Check for the absence of a cookie that begins with wordpress_logged_in_ 3. If these conditions are met, the file request will be denied via 403 “Forbidden” response The trick here is step 2, the check for the absence of a cookie that begins with wordpress_logged_in_. When the user is logged in, WordPress adds a cookie to your browser that looks like: wordpress_logged_in_1234567890abcdefghijklmnopqrstuvwxyz The appended alphanumerical string can be any sequence of (case-insensitive) letters and numbers. If such a cookie is not found, then the user is not logged in to WordPress, and thus Apache will return a 403 Forbidden response.