How to Password Protect a Link
Five real methods, with the trade-off each one makes. Pick by trust model and friction — not by which one shows up first in a search result.
Pick by what you actually need
"Password protect a link" can mean four different things, depending on your trust model. Before you pick a tool, decide which of these matters most:
- Convenience — fastest path from "I want this protected" to "the link works".
- The shortener can't read my destination — zero-knowledge sharing.
- The link can't be re-used after it's sent — single-use, expiring, or capped.
- I run the server — full control, no third-party dependency.
The five methods below sort cleanly along these axes. Read the comparison table at the bottom if you want the short version.
Method 1 — Password-protected short link
The general-purpose answer. A shortener service hosts the password page, hashes the password server-side, and redirects to your destination only after the visitor enters the right password.
How it works
Paste the URL, set a password, get back a short URL. Anyone who hits the short URL sees a password prompt; the destination is hidden.
curl -X POST http://zip1.io/api/create \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-site.com/private-page",
"password": "correcthorsebatterystaple"
}'
Trust model: the shortener stores your destination URL (so it can redirect) and the bcrypt hash of your password. Plaintext password never leaves the create request.
Strengths: fast, free (zip1.io, parts of Short.io / Dub), no signup, supports stacking with click caps and expiry, click analytics included.
Weaknesses: the shortener operator can read the destination URL. Not appropriate when the destination URL itself is the secret.
Right for: client previews, beta access links, gated downloads, internal docs shared in public channels — anywhere the destination is a real URL on a server you control.
Method 2 — In-browser AES (Link Lock, StatiCrypt)
Zero-server. The destination URL (or HTML page) is encrypted in your browser using a key derived from your password, and the ciphertext is embedded in the URL fragment or in a static HTML file. The recipient enters the password in their browser; the data decrypts locally.
Trust model: nothing reaches a server. The password and the destination only ever exist together in the browser of whoever generated and whoever opens the link.
Strengths: nobody else can read the destination — not the shortener operator, not a hosting provider, nobody. Ideal for genuine zero-knowledge use.
Weaknesses: the URL is long (the ciphertext rides along), there are no analytics, no click caps, no expiry, and the password is part of what the recipient needs to enter — so anything that captures the full URL and the password can decrypt it. AES-256 in the browser is only as strong as the password the user picked.
Right for: high-trust personal sharing, journalists or researchers handling sensitive sources, anything where the threat model includes the shortener operator.
Method 3 — .htaccess HTTP Basic Auth
The classic. If you control the web server, drop an .htaccess file and an .htpasswd file into a directory and Apache (or nginx with similar config) prompts every visitor for a username + password before serving anything in that directory.
What it looks like
# .htaccess
AuthType Basic
AuthName "Restricted"
AuthUserFile /var/www/.htpasswd
Require valid-user
# Generate the password file:
htpasswd -c /var/www/.htpasswd alice
Trust model: the password is stored hashed in .htpasswd on the server you run. The browser sends Basic Auth credentials with every request (over HTTPS).
Strengths: fully under your control, well-trusted, supported by every web server. No third-party dependency.
Weaknesses: the prompt is a browser dialog with a generic look, you maintain the password file by hand, the protection is per-directory not per-link, and there's no support for click caps or expiry. The browser caches the credentials for the session, so "log out" requires closing the tab.
Right for: a self-hosted staging site, an internal admin panel, anything you're already shipping behind your own infrastructure.
Method 4 — CMS-native passwords
Most CMSes have a per-page password feature. WordPress (Visibility → Password Protected), Webflow (Site or page password), Squarespace (Page Settings → Password), Wix (Set Permissions → Password Holders), Notion (Share → Anyone with link), Ghost (Page → Access). Toggle it on, type a password, save.
Trust model: your CMS stores the password (hashed in the better implementations, plaintext in some older ones — check your platform). The CMS enforces the gate before serving the page content.
Strengths: zero new tooling. The CMS already handles the page rendering; password protection is one toggle.
Weaknesses: only protects content that lives in your CMS. Doesn't help when the link points somewhere else (a Google Drive file, a YouTube video, a Loom recording, an external SaaS doc). The CMS-specific UI for the password page is hard to customize.
Right for: a single page on a CMS you already run. Not a fit when the destination is anywhere else.
Method 5 — Password manager share (Bitwarden Send, 1Password)
Strictly speaking this protects a secret, not a link. You paste the URL into a Bitwarden Send or a 1Password share, set an optional password and expiry, and send the share URL. The recipient enters the password, sees the original URL, and clicks through to it.
Trust model: the password manager stores the share encrypted with a key derived from the (optional) share password. End-to-end if the manager is built that way.
Strengths: if you already use 1Password / Bitwarden in a team, the workflow is right there. Good for sending credentials and documents-as-text.
Weaknesses: the protection ends at the share — once the recipient has the URL, it's just a URL. No analytics, no click cap on the underlying link, no integration with shorteners. Recipients without an account can usually open shares but with friction.
Right for: sharing the URL plus credentials, internal team hand-offs of sensitive references, one-off password drops to a known recipient.
The five methods at a glance
| Capability | 1. Short link wrapper | 2. In-browser AES | 3. .htaccess | 4. CMS-native | 5. Password mgr share |
|---|---|---|---|---|---|
| Free | Yes | Yes | Yes (you host) | CMS-dependent | Free tiers exist |
| Works for any URL | Yes | Yes | Only your server | Only your CMS | Yes |
| Zero-knowledge (server can't read destination) | No | Yes | If you're the server | No | Yes (E2E) |
| Click cap / single-use | Yes | No | No | No | Some support view limit |
| Click analytics | Yes | No | Server logs | CMS analytics | Read-receipt only |
| Friction to set up | Lowest | Low | Medium (server config) | Low (one toggle) | Medium (account) |
Default recommendation
For 90% of "I want to password-protect this one link" cases, Method 1 is the right answer. It's free, takes five seconds, the password is hashed server-side, and the same primitive supports click caps and expiry if you need them later.
Reach for Method 2 only when the destination URL itself is the secret — when "the shortener operator can read it" is the actual threat. Reach for Method 3 or Method 4 when you're already running the server or CMS and a one-toggle solution beats adding another tool. Method 5 is for the specific case of "I'm sending credentials, the URL just happens to be one of them."
FAQ
-
What about JavaScript-only password prompts on a static HTML page?
Don't. A page that hides content with
if (prompt() === "secret") show()is trivially bypassed by viewing the source. If you want client-side encryption on a static page, use StatiCrypt or PageCrypt — both encrypt the content with AES, so the source code itself is ciphertext. -
How long should the password be?
For a server-hashed password (Method 1, 3, 4), eight characters is a working minimum, twelve is comfortable, and a passphrase is better. For an in-browser-AES password (Method 2), longer matters more — 16+ characters since the ciphertext is sitting in plain view in the URL.
-
Should I rotate the password?
Yes, if the link is going to be shared widely or live for a long time. The fastest rotation is to mint a new short link with a new password and stop sharing the old one. zip1.io links are immutable once created, so rotation = new link.
-
What if the recipient forgets the password?
You re-send the password (or, in the server-hashed case, mint a new link with a new password — operators of bcrypt-hashed systems can't recover the original). Don't keep a plaintext copy of the password yourself; that defeats the hashing.
Related
Try Method 1 right now
Five seconds. No account. The lowest-friction password-protected link you can ship.