Generating a Vanity .onion Address with mkp224o: Complete Tutorial
.onion v3 addresses are 56 base32 characters long. By default, Tor generates them
randomly: dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion. Impossible to
memorize, easy to spoof via phishing — an attacker can generate an address that superficially resembles
yours. The solution: generate a vanity address, i.e., force a chosen prefix
(for example oniondir) by brute-forcing thousands of Ed25519 keys until finding one that
produces a fingerprint beginning with the desired prefix. The standard tool for this task is
mkp224o, developed by "cathugger." This tutorial covers installation, generation,
and integration into the Tor configuration.
Why a vanity address
Three main reasons justify the effort:
- Memorability —
oniondxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onionis recognizable at a glance, unlike a completely random address. Your users can visually verify the prefix, even if the remaining 50 characters are still impossible to memorize entirely. - Anti-phishing — an attacker who wants to impersonate your address would have to brute-force the same prefix, which costs exactly the same time as your own generation. For a 6–7 character prefix, this becomes prohibitive for opportunistic phishers.
- Editorial signaling — displaying a prefix signals that you've invested resources in the project. It's a seriousness signal appreciated by cautious dark web users.
Difficulty and computation time
.onion v3 addresses use 32 possible characters (base32: a–z + 2–7). The difficulty of finding a prefix of length n is therefore 32^n, and you need to try on average 32^n / 2 keys before landing on an address starting with that prefix.
| Prefix | Difficulty | Time on 8-core 2024 CPU |
|---|---|---|
| 3 chars | 32,768 | Instant |
| 4 chars | 1M | A few seconds |
| 5 chars | 33M | 1 to 5 minutes |
| 6 chars | 1 billion | 30 min to 3 h |
| 7 chars | 34 billion | 1 to 5 days |
| 8 chars | 1 trillion | 1 to 6 months |
GPUs (via the gpg-onion-finder fork or CUDA adaptations) divide these times by 20 to
100 depending on the card, making 8–9 characters achievable in under 1 week on an RTX 4090.
Installing mkp224o
Dependencies
On Debian / Ubuntu:
sudo apt install gcc libsodium-dev make autoconf On macOS (via Homebrew):
brew install libsodium autoconf automake On Fedora / RHEL:
sudo dnf install gcc libsodium-devel make autoconf automake Compilation
git clone https://github.com/cathugger/mkp224o.git
cd mkp224o
./autogen.sh
./configure
make
The ./mkp224o binary is created at the root. AVX2 optimizations are automatically
enabled if your CPU supports them (check with cat /proc/cpuinfo | grep avx2 on Linux).
Generating the address
Basic command to find an address starting with "onion" (5 characters):
./mkp224o -n 1 -d output onion -n 1: stops after finding 1 valid address-d output: output folderonion: the desired prefix (lowercase only, base32 so no 0, 1, 8, 9)
To search multiple patterns simultaneously, list them separated by spaces:
./mkp224o -n 1 -d output oniondir annuaire
To use all CPU cores (default), add -t N where N = number of threads:
./mkp224o -n 1 -d output -t 16 oniondir
During generation, mkp224o periodically displays its speed (keys/s) and progress.
At 8–10 million keys/second on a modern CPU, a 6-character prefix is found on average in 1–2 hours.
Verifying the produced files
When the tool finds an address, it creates a subfolder in output/ named after the full
address. Example:
output/oniondabc123xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion/
├── hostname (the full .onion address)
├── hs_ed25519_public_key (public key)
└── hs_ed25519_secret_key (private key — protect this)
Check the contents of hostname — this is the exact address that Tor will publish.
Installing on the Tor server
Transfer the folder to your server via SCP:
scp -r output/oniondabc123.../ root@your-server:/var/lib/tor/my-service/ On the server, adjust permissions (critical):
chown -R debian-tor:debian-tor /var/lib/tor/my-service/
chmod 700 /var/lib/tor/my-service/
chmod 600 /var/lib/tor/my-service/hs_ed25519_secret_key
chmod 600 /var/lib/tor/my-service/hs_ed25519_public_key
chmod 600 /var/lib/tor/my-service/hostname
The owner is debian-tor on Debian/Ubuntu, _tor on macOS (Homebrew),
tor on Fedora/RHEL. Check with ps aux | grep tor for the exact username.
torrc configuration
Add to /etc/tor/torrc:
HiddenServiceDir /var/lib/tor/my-service/
HiddenServiceVersion 3
HiddenServicePort 80 127.0.0.1:8080 127.0.0.1:8080 is the local port where your web server (nginx, Apache, Caddy) is
listening. Adjust according to your configuration.
Reload Tor:
systemctl restart tor
journalctl -u tor -f # follow logs If the configuration is correct, Tor publishes the hidden service descriptor to the DHT within 2–5 minutes. Open Tor Browser, type your .onion address: the service should respond.
Private key backup
Failing to back up the private key is the worst possible mistake. If your server crashes, is seized, or is reinstalled, you permanently lose the .onion address unless you have the key. No one can regenerate it — it is a random 32-byte number.
Recommended method
- Encrypt the
my-service/folder with GnuPG:tar czf - my-service/ | gpg -c > backup.tar.gz.gpg - Copy
backup.tar.gz.gpgto at least two separate physical media (encrypted USB stick + encrypted cloud storage, for example) - Store the GnuPG passphrase in a password manager (Bitwarden, KeePassXC)
- Test the restoration on a test machine before needing the backup in an emergency
Best practices
- Never commit the private key to git or any shared versioning system
- Generate on an isolated machine if the project is highly sensitive (Qubes OS, Tails, machine disconnected during generation)
- Use a prefix that includes your brand name or domain to strengthen anti-phishing
- Publish the address via a PGP-signed message on your official channels to prevent fraudulent variants from circulating
- Monitor for impersonation — services like OnionSearch or custom scanners can detect imitations of your prefix