🔒

Htpasswd Generator

Generate Apache .htpasswd entries with APR1 or SHA

Salted and iterated 1000 times. Portable across every platform Apache runs on and the default for `htpasswd -m`.

Hashing runs in this tab and nothing is uploaded — but generate credentials you intend to use with htpasswd on the server rather than in a browser.

Apache configuration
<Directory "/var/www/private">
    AuthType Basic
    AuthName "Restricted Area"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Directory>

A .htaccess file is ignored unless AllowOverride permits it, so a directory can appear unprotected with no error. Keep .htpasswd outside the document root.

bcrypt is not offered here. It needs a native implementation that browsers do not provide. If your Apache supports it, htpasswd -B -c .htpasswd user is the stronger choice — APR1 is the portable fallback, not the best one.

File Format

One user per line, username and hash separated by a colon:

`` admin:$apr1$xY7kL2mQ$8vN3pR5tW9zA1bC4dE6fG. deploy:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g= `

Duplicate usernames are ambiguous — Apache honours the first match — so replace an entry rather than appending a second one for the same user.

The Four Formats

FormatPrefixSaltedStrength
bcrypt$2y$YesStrongest; htpasswd -B, Apache 2.4+
APR1 (MD5)$apr1$Yes, 1000 roundsAdequate; portable everywhere
SHA-1{SHA}NoWeak; identical passwords hash identically
cryptnone2-char saltBroken; truncates at 8 characters
APR1 is Apache's own MD5-crypt variant. The underlying MD5 is broken for collision resistance, but APR1's salting and 1000-round iteration make it a genuine (if dated) password hash rather than a raw digest.

Wiring It Up

Apache:

`apache AuthType Basic AuthName "Staging" AuthUserFile /etc/apache2/.htpasswd Require valid-user `

nginx:

`nginx location / { auth_basic "Staging"; auth_basic_user_file /etc/nginx/.htpasswd; } `

Doing It on the Server Instead

If you have shell access, generate the file where it will live:

`bash # Create with bcrypt (best) htpasswd -B -c /etc/apache2/.htpasswd admin

# Add another user (note: no -c, which would overwrite) htpasswd -B /etc/apache2/.htpasswd deploy

# APR1, for portability htpasswd -m /etc/apache2/.htpasswd legacy `

The -c flag creates a new file, destroying any existing one. Using it twice is the classic way to lock everyone out.

Security Checklist

  • Serve over HTTPS only — basic auth is cleartext-equivalent otherwise.
  • Keep the file outside the document root.
  • chmod 640 and own it by the web server user.
  • Rotate credentials when someone leaves; there is no session to revoke.
  • Do not use basic auth for real user accounts — it has no logout, no lockout and no MFA.

What an .htpasswd File Is

One line per user, a colon between the username and the hash:

` alice:$apr1$Zx8yQ2mK$3v9pLnR4wT6sK2mB8cN1e/ bob:{SHA}qUqP5cyxm6YcTAhz05Hph5gvu9M= `

The prefix identifies the algorithm, so a single file can mix formats — which makes migrating from one to the other straightforward. Both Apache and nginx read the same file.

FormatPrefixSaltedIterated
APR1 (Apache MD5)$apr1$YesYes, 1,000 rounds
SHA-1{SHA}NoNo
bcrypt$2y$YesYes, tunable
Use [APR1](/dev/htpasswd-generator/apache-htpasswd-generator) unless something specifically demands otherwise. [{SHA}](/dev/htpasswd-generator/sha1-htpasswd-generator) exists for LDAP interoperability and legacy appliances; it is unsalted, so identical passwords produce identical hashes and rainbow tables apply directly.

Neither Format Is a Modern Password Hash

APR1 is iterated MD5. A GPU tries billions of MD5 operations per second, so a weak password behind an APR1 hash falls quickly, and {SHA} is worse. bcrypt is the right choice where it is available — htpasswd -B produces it — but browsers cannot generate it, because it needs a native implementation.

The practical consequence: the password must carry the security the hash does not. Generate a long random one, never reuse it, and treat the hash file as sensitive even though it is hashed.

Where Basic Auth Belongs

Basic auth is infrastructure gating, not user authentication. It has no session, no logout, no lockout, no password reset and no rate limiting, and it sends base64(user:password) on every single request.

Good uses: a staging site, an internal dashboard, a metrics endpoint, a directory you want kept off the open web. Bad uses: anything with real user accounts.

Over HTTPS the repeated transmission is acceptable. Over plain HTTP it is a plaintext password on the wire, hundreds of times a session — Base64 is encoding, not encryption.

The Three Configuration Mistakes

1. The password file is inside the web root. Then it can be requested over HTTP and downloaded, handing over every hash in it. Put it somewhere like /etc/apache2/.htpasswd, outside anything the server will serve.

2. AllowOverride is not set. Apache silently ignores a .htaccess file it is not configured to read, so the directory is completely unprotected and nothing logs an error. Always test with a private browser window before assuming a directory is protected.

3. The path is relative. AuthUserFile needs an absolute path.

The [nginx](/dev/nginx-basic-auth-generator) and [Apache](/dev/htpasswd-generator/apache-htpasswd-generator) pages each show the directives for their own server, because the hash is the same and the configuration around it is not.

Layer Something Else On Top

Where the client set is known, restrict by IP as well as by password — two independent controls fail independently. Rotate the password when anyone with access leaves, since Basic auth has no per-user revocation beyond editing the file.

Generated Locally

The salt comes from crypto.getRandomValues()` and the hash is computed in your browser. The password is never transmitted, which is the entire reason not to use an online generator that posts it to a server before hashing it.

Frequently Asked Questions

Which hash format should I use?

bcrypt (htpasswd -B) if your Apache is 2.4 or newer — it is the strongest option. APR1 is the portable fallback and what this tool generates, since bcrypt needs a native library a browser cannot provide. Avoid plain SHA-1 and crypt unless a legacy system forces them.

Does nginx accept these files?

Yes. nginx reads the same file format for auth_basic_user_file and supports APR1 and {SHA} entries. It does not support bcrypt on all builds, which is one reason APR1 is still common.

Is basic auth secure?

Only over HTTPS. Basic auth sends base64-encoded credentials on every request — base64 is encoding, not encryption. Over plain HTTP anyone on the path reads the password. It is fine for staging gates and internal tools behind TLS, and wrong for user-facing authentication.

Where does the .htpasswd file go?

Outside the web root, always. If it sits in a served directory, someone can download your hashes. Point AuthUserFile at something like /etc/apache2/.htpasswd and keep it readable only by the web server user.

Related Tools

Explore other tools you might find useful:

Specialized Versions

Try our targeted calculators for specific use cases: