htpasswd Generator — bcrypt, Apache MD5 (apr1) & Basic Auth
Generate htpasswd entries with bcrypt, Apache MD5 (apr1), SHA-1 & more. Get ready-to-paste Apache, nginx & Docker config. 100% in your browser — no upload.
Verify an existing hash
What Is an htpasswd File?
An .htpasswd file stores the credentials used by HTTP Basic Authentication. Each line is a single username:hash pair, where the hash is a one-way digest of the password — the plaintext is never stored. Web servers read this file to decide who may access a protected URL. On Apache, a .htaccess file (or a <Directory> block) references the .htpasswd file and prompts the browser for a username and password before serving the page.
The hash format depends on which algorithm produced it. Apache's htpasswd tool can emit several: bcrypt (lines starting with $2y$) is the strongest and is recommended for Apache, Docker Registry, and Caddy; apr1 (Apache MD5, starting with $apr1$) is the most portable and the safe default for nginx; SHA-1 (starting with {SHA}) is unsalted and considered insecure; crypt (traditional DES) is legacy and truncates at 8 characters; and plain stores the password in cleartext, which should never be used in production.
This generator runs entirely in your browser — no username, password, or hash is ever uploaded. If you need a strong password to go with your entry, use our Random Password Generator. To build the Authorization: Basic header by hand, the credential is just base64(user:password), which you can produce with our Base64 Encoder. And once your endpoint is protected, test it from the command line with our cURL Command Builder.
# Apache htpasswd CLI equivalents (apache2-utils / httpd-tools) # bcrypt entry, printed to stdout (recommended; -B = bcrypt, -n = no file, -b = password on CLI) htpasswd -Bbn admin 's3cret' # → admin:$2y$10$N9qo8uLOickgx2ZMRZoMye... # apr1 (Apache MD5) entry, portable for nginx — no apache2-utils needed printf "admin:$(openssl passwd -apr1 's3cret')\n" # → admin:$apr1$k3l4Hj9.$qN8... # Append a user to an existing file from the shell htpasswd -B /etc/apache2/.htpasswd alice # Note: nginx delegates bcrypt to the system crypt(); on Alpine/musl or old # glibc that fails — prefer apr1 for nginx to stay portable.
Key Features
Multiple Hash Algorithms
Generate bcrypt ($2y$), apr1 / Apache MD5 ($apr1$), and SHA-1 ({SHA}) entries — plus a plain (cleartext) option for testing. Each uses a fresh cryptographic salt where the format supports one.
Generate and Verify
Create new entries or verify existing ones. Paste a stored user:hash line and a candidate password to confirm instantly whether they match — useful for debugging a 401 in production.
Choose by Server
Pick Apache, nginx, Docker, or Caddy and the correct algorithm is selected automatically — bcrypt where it's supported, apr1 for nginx portability — so you avoid silent crypt() failures.
Ready-to-Paste Config Blocks
Get six copy-ready configuration snippets — Apache .htaccess, nginx auth_basic, Docker, Kubernetes ingress-nginx, Caddy, and Traefik — already wired to your generated .htpasswd entry.
100% Client-Side
All hashing happens locally in your browser via Web Crypto and a bundled bcrypt implementation. No username, password, or hash is ever sent to a server, so you can generate production credentials privately.
Examples
bcrypt entry (recommended)
admin:$2y$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
A bcrypt entry with a $2y$ prefix and cost 10. This is the strongest, most portable format — use it for Apache, Docker Registry, Caddy, and Traefik.
apr1 entry (portable nginx)
admin:$apr1$kl3H9j2.$qN8vY7tLp2mZ0xW5cR4fK1
Apache MD5 (apr1) with an 8-character salt after the $apr1$ marker. The safe default for nginx, where bcrypt verification depends on an unreliable system crypt().
SHA-1 entry (legacy)
admin:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g= A {SHA} entry is the base64 of an unsalted SHA-1 digest. Apache and nginx accept it, but it's unsalted and insecure — included only for legacy compatibility.
Authorization: Basic header
Authorization: Basic YWRtaW46czNjcmV0
The client-side credential for the same user: base64('admin:s3cret'). Send this header with curl -H or Postman to authenticate without writing a .htpasswd file.
Multi-user .htpasswd file
admin:$2y$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy alice:$2y$10$3bQ8xY7tLp2mZ0xW5cR4fO9vK1jH6sD2nG8aQ5wE3rT7uI4oP1cm bob:$apr1$mZ0xW5cR$4fK1jH6sD2nG8aQ5wE3rT2
One username:hash line per user. Algorithms can be mixed in the same file — here two bcrypt entries and one apr1 entry coexist for three users.
How to Use
- 1
Configure Server & Algorithm
Pick your target server (Apache, nginx, Docker, Caddy). The right algorithm is auto-selected — bcrypt for Apache/Docker/Caddy, apr1 for portable nginx — but you can override it and tune the bcrypt cost.
- 2
Generate the Hash
Enter a username and password (or click Random password), then click Generate. The hash is computed locally with a fresh random salt. Re-roll the salt anytime to mint a new entry.
- 3
Copy the Entry
Copy the user:hash line for your .htpasswd file, copy the echo >> append command for the shell, or copy the Authorization: Basic header for curl and Postman.
- 4
Deploy the Config
Paste the generated config block into your Apache .htaccess, nginx server block, Docker, Kubernetes ingress, Caddy, or Traefik configuration, point it at your .htpasswd file, and reload the server.
Common Use Cases
- Apache Directory Protection
- Lock down a folder with HTTP Basic Auth using a .htaccess file and an AuthUserFile directive. Drop in the bcrypt entry and the generated Apache config block to require a login on any path.
- nginx auth_basic
- Protect a location or server block with auth_basic and auth_basic_user_file. Use the apr1 format so verification works reliably across Alpine, Debian, and other base images.
- Docker Registry
- A private Docker Registry only accepts bcrypt htpasswd entries. Generate a $2y$ line with htpasswd -Bbn, mount it into the registry container, and authenticate your docker login.
- Kubernetes ingress-nginx
- Create a basic-auth Secret from your .htpasswd file and reference it with the nginx.ingress.kubernetes.io/auth-type and auth-secret annotations to gate an ingress route.
- Caddy & Traefik
- Caddy's basic_auth directive and Traefik's basicauth middleware both expect bcrypt hashes. Paste the generated entry directly into your Caddyfile or Traefik labels/dynamic config.
- curl & Postman Authorization Header
- Skip the file entirely for quick tests: copy the Authorization: Basic header to send credentials directly. Drop it into a curl -H flag or a Postman request to hit a protected endpoint.
Technical Details
- bcrypt ($2y$)
- An adaptive, salted hash based on the Blowfish cipher with a tunable cost factor. Each entry embeds a random 16-byte salt and the cost, so identical passwords produce different hashes. Note: bcrypt truncates the password at 72 bytes — characters beyond that are ignored.
- apr1 (Apache MD5)
- Apache's iterated, salted MD5 variant ($apr1$ + 8-char salt). It runs 1,000 MD5 rounds, which is far weaker than bcrypt's adaptive cost, but it is implemented natively by Apache and nginx, making it the most portable format across platforms and base images.
- SHA-1 and crypt
- SHA-1 entries ({SHA} + base64 digest) are unsalted, so identical passwords yield identical hashes and are vulnerable to rainbow tables — included only for legacy compatibility. Traditional crypt (DES) is even weaker and silently truncates passwords at 8 characters.
- Salt & Iterations
- Salting prevents precomputed (rainbow-table) attacks by making every hash unique. bcrypt uses a 128-bit random salt with a configurable cost; apr1 uses an 8-character salt with 1,000 fixed iterations. Use Re-roll salt to regenerate a different valid hash for the same password.
- Base64 & UTF-8 Handling
- Passwords are encoded as UTF-8 bytes before hashing, so non-ASCII characters are handled consistently. The Authorization: Basic header is the base64 of the raw UTF-8 username:password bytes, matching what servers decode on the receiving end.
- Honesty Notes & Caveats
- Generated hashes are computed locally and never verified against a live server. Copied entries and downloaded .htpasswd files land on your clipboard and disk in plaintext-hash form — handle them like secrets, restrict file permissions, and clear your clipboard after pasting into production config.
Best Practices
- Prefer bcrypt Wherever Supported
- Use bcrypt ($2y$) for Apache, Docker, Caddy, and Traefik — it's salted, adaptive, and far stronger than apr1 or SHA-1. Reserve apr1 for nginx only when bcrypt's reliance on the system crypt() makes it unreliable.
- Store the File Outside the Web Root
- Keep .htpasswd out of any served directory so it can never be downloaded over HTTP. Set chmod 640 and own it by the web-server user so the server can read it while other accounts cannot.
- Always Serve Over HTTPS
- Basic Auth transmits credentials as reversible base64 on every request. Without TLS, anyone on the network path can read the password. Never enable Basic Auth on plain HTTP — terminate TLS in front of the protected endpoint.
- Use Unique, Strong Passwords
- Each account should have its own high-entropy password, never reused across services. Generate one with our Random Password Generator and store it in a password manager rather than inventing it by hand.
Frequently Asked Questions
bcrypt vs apr1 — which should I choose?
Does nginx support bcrypt?
How do I fix the nginx error `crypt_r() failed (22: Invalid argument)`?
Where should I put the .htpasswd file and what permissions?
How do I configure Basic Auth in .htaccess / nginx?
Are my passwords uploaded anywhere?
What's the difference between $2a$, $2b$, and $2y$ in bcrypt?
What bcrypt cost should I use?
htpasswd vs the Authorization: Basic header — what's the difference?
I don't have apache2-utils installed — how do I generate an htpasswd entry?
What do the htpasswd flags -B, -Bbn, -bnB mean?
Why does Docker Registry require bcrypt?
Is Basic Auth secure?
Related Tools
View all tools →cURL Command Generator & Builder
Web & API
Build curl commands in your browser — set method, headers, auth, and body, get a copy-ready command instantly. Presets for Bearer, POST JSON, file upload. Free, private, no signup.
Number Base Converter — Binary, Hex, Decimal & Octal
Conversion Tools
Convert between binary, hex, decimal, octal and any base (2-36) instantly. Free, private — all processing in your browser.
Base64 Decoder & Encoder
Encoding & Formatting
Decode and encode Base64 online for free. Real-time conversion with full UTF-8 and emoji support. 100% private — runs in your browser. No signup needed.
Case Converter — UPPERCASE, lowercase, camelCase & More
Text Processing
Convert text between UPPERCASE, lowercase, Title Case, Sentence case, camelCase, PascalCase, snake_case, kebab-case, CONSTANT_CASE and 6 more formats instantly. Free, browser-only, no signup.
Color Converter — HEX, RGB, HSL & OKLCH
Conversion Tools
Convert HEX to RGB, HSL, OKLCH, OKLAB and CMYK in your browser — copy any format with one click. Free, no signup, your colors never leave the page.
Crontab Generator & Cron Expression Builder
Date & Time
Build, validate, and decode cron expressions in your browser. Live next-run preview in local time or UTC. POSIX 5-field syntax, presets, plain-English description. Free, private, no signup.