htpasswd Generator

Build .htpasswd lines for Apache and nginx in your browser, with apr1 and SHA-512 crypt, random salts and copy-ready snippets.

This htpasswd generator builds the password lines Apache and nginx read for HTTP basic auth, and it does the whole job inside your browser so the password never travels to a server. Type a username and password, pick Apache MD5 (apr1), SHA-512 crypt or the legacy SHA-1 format, and you get a ready-to-paste line hashed locally with a fresh random salt from crypto.getRandomValues. Stack up as many users as you need, then copy the whole file. Because hand-rolled crypto fails quietly, the page checks its own apr1 and SHA-512 crypt code against known test vectors at load. It also ships copy-ready nginx and .htaccess snippets, plus the honest bcrypt command to run on the server.

100% in your browser. Nothing you type ever leaves this page.

Client-side .htpasswd builder for Apache and nginx

Basic auth is the duct tape of web security, and I mean that as a compliment. The annoying part is that nearly every .htpasswd generator out there wants to send your password to somebody else's server first, which defeats the entire point. This one doesn't. Type a username and a password, pick a format, and you get a ready-to-paste .htpasswd line, hashed right here in your browser with a fresh random salt from crypto.getRandomValues. Stack up as many users as you need, then copy the whole file. And because hand-rolled crypto fails quietly, this page verifies its own APR1-MD5 and SHA-512 crypt implementations against known test vectors every single time it loads. If a check fails, you see a red banner instead of a wrong hash.

Your passwords never leave this page. The hashing is plain local JavaScript, salts come from crypto.getRandomValues, and you can keep the network tab open to watch nothing happen. The password field stays visible on purpose, so you can see what you're hashing.

Your .htpasswd file

 
About bcrypt: it's the strongest format htpasswd supports, and I can't generate it here without shipping a huge third-party library I can't verify. So I won't. Make bcrypt lines on the server instead: htpasswd -B -c /etc/nginx/.htpasswd alice (drop -c once the file exists), or htpasswd -nbB alice 'YourPassphrase' to just print the line.

nginx snippet

 

Apache .htaccess block

# .htaccess in the directory to protect
AuthType Basic
AuthName "Restricted area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

What this htpasswd generator does

This htpasswd generator builds the password lines Apache and nginx read for HTTP basic auth, and it does the whole job inside your browser so the password never travels to a server. An .htpasswd file could not be simpler: one line per user, the username, a colon, then the password hash. The prefix on that hash tells the server which scheme to run when somebody tries to log in, and that prefix is where the real decision lives. Type a username and password, pick a format, and you get a line you can paste straight into the file. Add as many users as you need, then copy the lot.

How the formats differ, and which to pick

  • $apr1$ is Apache's own MD5 variant: a thousand rounds over an 8 character salt, with a quirky custom base64 alphabet. It is old, but the salt and the iterations keep it well clear of plain-MD5 territory, and compatibility is unbeatable. Apache, nginx, lighttpd, ancient NAS boxes, they all take it.
  • $6$ is SHA-512 crypt, the glibc crypt(3) scheme: 5000 rounds by default over a 16 character salt. Stronger than apr1 on every axis. The catch is support. nginx verifies it through the system crypt() function, which handles it on any normal Linux, while Apache only learned the scheme fairly recently. Test one login before you rely on it.
  • The legacy SHA-1 format is just the base64 of an unsalted SHA-1 digest. No salt at all, so two users with the same password get identical lines. It is here for legacy interop, nothing else.
  • bcrypt is deliberately slow, which is exactly what you want against GPU cracking rigs. This page will not fake it; run htpasswd -B on the server instead.

Why basic auth still has a place

It is fashionable to sneer at HTTP basic auth, and I get it. No lockout, no sessions, a login box that looks like 1997. And yet, when you need to keep a staging site away from Google and from your client's boss until launch day, basic auth is two lines of config and one file. No signup flow, no JavaScript, no session store to babysit. Every server and every browser shipped since the 90s understands it. I use it as a second fence in front of admin panels too: a bot has to get through the basic auth prompt before it can even start hammering the real login form, and most never bother.

Security caveats, honestly

HTTPS or nothing. With basic auth the credentials travel base64-encoded in a header with every single request, and base64 is encoding, not encryption. Anyone reading the wire on plain HTTP gets the password verbatim. There is no built-in lockout either, so the hash speed and the password length carry the whole defense. That is the real reason bcrypt beats apr1: an MD5-based hash runs absurdly fast on a GPU, billions of guesses a second fast, and a long passphrase narrows that gap more than any format choice does. Pair the endpoint with fail2ban or nginx rate limiting if it matters, keep the file outside the web root with permissions only the server user can read, and do not reuse a password you care about.

Frequently asked questions

Is it safe to type a real password into this page?

Nothing you type here leaves your browser. There's no form submit and no fetch; the hashing runs as local JavaScript and the salts come from crypto.getRandomValues. You can pull the network tab open and watch nothing happen. That said, for production credentials a healthy paranoia is fine: generate them on the server with htpasswd and its password prompt, and this page won't be offended.

Why is there no bcrypt option?

Because I couldn't do it honestly. bcrypt in the browser means shipping a large third-party library, and this page refuses to emit any hash it can't verify against known test vectors at load. So instead of a fake option you get the real command: run htpasswd -B -c /etc/nginx/.htpasswd alice on the server and you'll have a proper bcrypt line in seconds.

Which format should I actually pick?

bcrypt first, if you can run one command on a server. After that, apr1 is the compatibility king: every Apache and nginx out there accepts it. SHA-512 crypt is stronger on paper but support depends on your server's crypt() implementation, so test it once before rolling it out. The legacy SHA-1 format is unsalted and exists here for old systems only.

Where should the .htpasswd file live?

Outside the web root, full stop. /etc/nginx/.htpasswd or /etc/apache2/.htpasswd are the usual homes. Apache blocks requests for files starting with .ht by default, but that's a seatbelt, not a reason to park the file in a public directory. And check permissions: the server user needs read access, nobody else does.

Does nginx accept all these formats?

apr1 and the legacy SHA-1 format work everywhere nginx runs. For SHA-512 crypt, nginx hands verification to the system crypt() function, which handles it on any normal Linux. bcrypt lines work too when the system libcrypt knows the scheme, which modern distributions using libxcrypt do. When in doubt, create one test user and try logging in before you protect anything real.

Is basic auth actually secure?

Over HTTPS, it's a reasonable gate. Over plain HTTP it's nothing: the credentials travel base64-encoded with every single request, and base64 is encoding, not encryption. There's also no built-in lockout, so pair it with rate limiting or fail2ban if the endpoint matters. I'd happily use it to keep a staging site private. I would not use it as the only authentication on anything holding user data.