Why generate an APR1-MD5 hash online?
HTTP Basic authentication is still the fastest way to close off an admin area, a staging site or an internal dashboard. It relies on a .htpasswd file where every line maps a username to a hashed password - never to a plaintext one.
The catch: producing that hash normally requires the htpasswd command, which means the apache2-utils package on Debian or httpd-tools on RHEL. On a Windows workstation, on shared hosting or from a web console, that command is often missing.
Three situations where this generator helps:
- Lock down a staging site → Close off a preview environment before Google indexes it
- Add an account without SSH access → Build the line in your browser and paste it through your host's file manager
- Migrate a configuration → Rebuild a lost
.htpasswdfile from the credentials you still know
How to use the generator in 3 steps
Step 1: Enter the username and password
Type the account name, then its password. The field is masked by default; click the eye icon to re-read what you typed before submitting.
Step 2: Let the salt be generated
In almost every case, leave the salt field empty: a random 8-character salt is drawn server-side. Only fill it in to reproduce an existing hash byte for byte.
Step 3: Copy the line
Two results are shown: the hash on its own, and the complete .htpasswd line. Copy the latter, paste it into your file, then reload the server configuration.
Anatomy of a .htpasswd line
A line splits into two fields separated by a colon:
admin:$apr1$Xq7nD2mR$5CqLZ.k1qLkOvVQ0uZ9Yl.
The second field itself splits into three parts delimited by $:
| Part | Example | Role |
|---|---|---|
| Algorithm identifier | apr1 | Tells the server this is Apache's salted MD5 |
| Salt | Xq7nD2mR | 8 random characters, stored in clear in the file |
| Digest | 5CqLZ.k1qLkOvVQ0uZ9Yl. | 22 characters, the output of the 1,000 iterations |
The salt is not a secret: it is readable in the file. Its job is to stop a pre-computed table (a rainbow table) from recovering the password, and to guarantee that two accounts sharing a password do not share a digest.
What the $apr1$ algorithm actually does
APR1-MD5 is not a plain md5(password + salt). It chains:
- Two initial digests - one over
password + $apr1$ + salt, the other overpassword + salt + password - A length-dependent mix - fragments of the second digest are folded back into the first, byte by byte
- 1,000 iterations - on each round, password, salt and previous digest are recombined following a pattern that depends on the round number
- A crypt base64 encoding - the final 16 bytes are read back in an interleaved order, then encoded over the
./0-9A-Za-zalphabet
Those 1,000 iterations are what separates it from a bare MD5: they multiply the cost of a single guess by a thousand, which slows a dictionary attack down by the same factor.
Protecting a directory with Apache
1. Create the file
Put your .htpasswd file outside the web root, so that it can never be served over HTTP:
/var/www/secrets/.htpasswd
2. Declare the protection
In the .htaccess of the directory to protect, or in the <Directory> block of your VirtualHost:
AuthType Basic
AuthName "Restricted area"
AuthUserFile /var/www/secrets/.htpasswd
Require valid-user
3. Reload the configuration
sudo apachectl configtest && sudo systemctl reload apache2
For nginx, the same pair of files is declared like this:
location /admin/ {
auth_basic "Restricted area";
auth_basic_user_file /var/www/secrets/.htpasswd;
}
APR1-MD5 versus the other .htpasswd formats
| Format | Prefix | Computation cost | Verdict |
|---|---|---|---|
| bcrypt | $2y$ | Tunable (cost factor) | Recommended for any new project |
| APR1-MD5 | $apr1$ | 1,000 MD5 iterations | Acceptable, maximum compatibility |
| SHA-1 | {SHA} | 1 iteration, unsalted | Avoid: no salt, breakable by table lookup |
| crypt() DES | none | 25 iterations, truncated at 8 characters | Obsolete, do not use |
In short: if your server accepts bcrypt (htpasswd -B), use it. APR1-MD5 is the best remaining option when bcrypt is unavailable - and it is vastly better than an unsalted {SHA}.
Verifying the hash on the command line
Given the same salt, this tool returns exactly what the system utilities return:
# With htpasswd (apache2-utils / httpd-tools package)
htpasswd -nbm admin myPassword
# With OpenSSL, forcing the salt
openssl passwd -apr1 -salt Xq7nD2mR myPassword
The second example doubles as a check on this tool: enter the same salt in the form and you should get exactly the same string back.
To verify that a password matches an existing line, read the salt out of the stored hash and replay the computation with that salt.
FAQ - Frequently asked questions
Q: What is the $apr1$ format?
A: It is Apache's historical password format, also called APR1-MD5. It runs 1,000 MD5 iterations over the password and an 8-character salt, then encodes the result in the crypt base64 alphabet. The $apr1$ prefix acts as the algorithm identifier.
Q: Is APR1-MD5 still safe?
A: It is far stronger than a bare MD5, but it stays cheap to compute for an attacker with GPUs. For a new project, prefer bcrypt through htpasswd -B. APR1-MD5 keeps its value where compatibility comes first: older Apache versions, nginx without bcrypt support, network appliances.
Q: Does this hash work with nginx?
A: Yes. The nginx ngx_http_auth_basic_module reads the Apache format, $apr1$ included. The generated line works as-is with auth_basic_user_file.
Q: Why do I get a different hash every time?
A: A new random salt is drawn on every generation. Both hashes are valid for the same password: on verification, the server reads the salt stored inside the hash and redoes the computation. Fill in the salt field if you want a reproducible result.
Q: Is the password stored anywhere?
A: No. It travels over HTTPS to the CaptainDNS API for the duration of the computation, then it is discarded. No database, no log holding the plaintext password.
Q: Can I use accented characters or symbols?
A: Yes, the computation runs over the UTF-8 bytes of the password. One caveat: an old HTTP client may encode non-ASCII characters differently, which would make authentication fail. When in doubt, stay in ASCII.
Q: Where should the .htpasswd file live?
A: Outside the web root, for instance in /var/www/secrets/. If it sits in a directory served over HTTP, a visitor could download it and attack the hashes offline.
Related tools
| Tool | What it does |
|---|---|
| Password generator | Draw a strong password before hashing it |
| Hash generator | Compute MD5, SHA-1, SHA-256 and SHA-512 of a text |
| Base64 encoder | Encode the Authorization header of a Basic request |
| HTTP headers viewer | Check the headers returned by a protected area |
| HSTS test | Make sure protected access really runs over HTTPS |
Useful resources
- Apache documentation - htpasswd (command options and supported formats)
- Apache documentation - Authentication (setting up Basic authentication)
- RFC 7617 - The Basic HTTP Authentication Scheme (specification of the Basic scheme)
- RFC 1321 - MD5 (specification of the MD5 function)
Privacy commitment
Your password is sent to the CaptainDNS API for the sole purpose of computing the hash, over an encrypted connection. It is neither stored nor logged. Only anonymous technical metrics are kept (processing time, response code).