When you have a work-in-progress site on shared hosting that you need to show clients but don't want public access or search engine crawling, Apache's .htpasswd and .htaccess files provide a simple solution (for the technicaly inclined).
Core Concepts
.htpasswd — A flat-file database containing usernames and hashed passwords (one per line). Passwords are never stored in plain text.
.htaccess — An Apache configuration file that enforces authentication before allowing access to a directory.
Server Compatibility:
| Server | Works? |
|---|---|
| Apache | ✓ Yes (most shared hosting) |
| Nginx | ✗ No (different auth method) |
| LiteSpeed | ✓ Maybe (check with host) |
| IIS | ✗ No |
Practical Setup
Step 1: Generate Password Hash
Visit htpasswdgenerator.de and:
NoteSometimes, the above site has NOT worked for me. Try instead: https://www.htpasswdgenerator.net/ or https://codeshack.io/htpasswd-generator/. I personally prefer using ssh in terminal (mentioned in advanced mode)
- Enter username (e.g.,
testadmin) - Enter password
- Select bcrypt encryption
- Copy output like:
testadmin:$2y$10$eImiTXuWVxfaHNYY8Ps0.eHDwnjYkCqP3bQ8WCPvPLV2Rqph5Z.R6
Tradeoff: You're sending your password to a third-party generator. For test/staging sites this is acceptable; for production auth, use terminal methods (see Advanced section).
Step 2: Create .htpasswd File
Upload via FTP to your protected directory:
/public_html/testsite/.htpasswd
Contents (paste the hash):testadmin:$2y$10$eImiTXuWVxfaHNYY8Ps0.eHDwnjYkCqP3bQ8WCPvPLV2Rqph5Z.R6
Step 3: Create .htaccess FileIn the same directory:
<FilesMatch ".*">
AuthType Basic
AuthName "Test Site - Work in Progress"
AuthUserFile /home/[youruser]/public_html/testsite/.htpasswd
Require valid-user
Step 4: TestVisit https://yourdomain.com/testsite/ — a login dialog should appear. Wrong password blocks access; correct password grants it.Alternatives Worth Considering
Not ready to edit files? Most hosting control panels (cPanel, DirectAdmin, HestiaCP) have a built-in "Password Protected Directories" tool that generates these files for you through a GUI. It's faster but doesn't teach you how it works.
Other options you might evaluate:
PHP session-based login — More complex, requires PHP on every request
IP whitelisting — Good if client has fixed IPs, but less flexible
Static hosts (Netlify/Vercel) — Built-in password protection if you move away from shared hosting
Advanced Options
More Secure Password Generation (SSH/Terminal)
If you have SSH access (VPS or local terminal), avoid online generators entirely: # APR1 method openssl passwd -apr1 mypasswordOr bcrypt (more secure)
$ htpasswd -nbB username mypassword
Create file directly with htpasswd utility
$ htpasswd -bc /path/to/.htpasswd username password
Multiple Users and Granular Control
Add more users — Just add new lines to .htpasswd:testadmin:$2y$10$... client:$2y$10$... designer:$2y$10$...Restrict to specific user only: Require user testadmin Protect specific file types:
Security Considerations
Important notes:HTTP Basic Auth sends passwords in Base64, not encrypted. Always use HTTPS. Force it with:
RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Browsers cache credentials — logout requires closing the browser or using incognito mode.
For VPS/production setups: Store .htpasswd outside the web root (e.g., /home/username/.htpasswd instead of /public_html/testsite/) to prevent accidental exposure.
Use bcrypt or APR1 — Avoid older SHA-1 hashing algorithms.
Troubleshooting
ProblemFixLogin prompt doesn't appearCheck .htaccess path to .htpasswd; verify host enables .htaccess overrides"Authorization Required" errorAuthUserFile path is wrong — use absolute path"Internal Server Error" (500)Syntax error in .htaccess — validate at htaccesstools.comWrong password acceptedHash was created incorrectly — regeneratePassword works then failsBrowser cached old credentials — clear cache or use incognitoThis method trades GUI convenience for understanding the underlying mechanics. Once you know how it works, you can implement it anywhere Apache runs, independent of any control panel.