A Nostr profile that works: images, NIP-05, Lightning, relays
- 1. Picture and banner: host them so they don’t vanish
- 2. Name and bio: three short lines
- 3. NIP-05: the identifier that should show a check mark
- 4. Lightning address: make zaps actually land
- 5. Publish the profile so people actually see it
- The ten-minute self-check
Most Nostr profiles that “don’t work” are not broken in an exotic way. The avatar points at a file that no longer exists. The NIP-05 check mark never appears because the server answers a browser but not a client. Zaps fail and the wallet gets blamed. Or the profile was updated, but half the relays still serve last month’s version.
None of this needs a developer. It needs an hour, a terminal or a browser, and a short list. This guide walks through the five parts of a profile in the order people see them, explains what can go wrong with each, and ends with a self-check you can run in ten minutes.
1. Picture and banner: host them so they don’t vanish
Your kind 0 profile event does not contain your images. It contains links to them. If the file behind the link disappears, every client shows a blank circle, and unless you planned for it, nothing in your profile can fix that.
Use sensible sizes. A square avatar of 400 to 1024 px is plenty. Make sure it still reads at 40 px, because that is how most people will see it in a feed: one shape, strong contrast, little detail. For the banner, a wide image around 1500 × 500 works in most clients. Keep text and faces near the middle, because clients crop banners differently.
Prefer Blossom, and don’t rely on a single server. Blossom servers store files by their SHA-256 hash, so the address ends in a 64-character hex string, for example https://<server>/<sha256>.jpg. That has a useful consequence: the same file has the same name on every Blossom server. If one server drops it, the identical file can be served from another one.
Servers do drop files: they go offline, change policy, or quietly lose blobs. So:
- Upload the same image to at least two Blossom servers. Many clients and tools can mirror for you.
- Publish your server list (a
kind:10063event with oneservertag per server, most reliable first). Under NIP-B7, when a hash-named URL stops working, clients should look up the same hash on the servers in your list and check that the bytes match the hash. - Add fallbacks to the profile itself. NIP-92 now lets a kind 0 event carry
imetatags forpictureandbanner, includingfallbackURLs that clients should try when the main URL fails. It is a recent addition and not every client reads it yet, so treat it as an extra layer, not a replacement for the two steps above.
Check it, don’t assume it. Open the image URL in a private window. If you have a terminal, this confirms the file is there and unchanged:
curl -sL https://<server>/<sha256>.jpg | sha256sum
The output must equal the hash in the file name. Do this once a month, and after any client or host change.
2. Name and bio: three short lines
Clients show display_name big and name small, and some only show name, so set both. Then write the bio for someone deciding in two seconds whether to follow you:
- Who you are, in plain words.
- What you post or do.
- How to reach you or where to find your work.
A paragraph of hashtags or a single emoji tells a new contact nothing. Add a website if you have one page you actually maintain.
3. NIP-05: the identifier that should show a check mark
NIP-05 maps a name like you@example.com to your public key. It is identification, not a blue tick from an authority: it proves that whoever controls example.com vouches for this key.
How it works. A client sees "nip05": "you@example.com" in your profile and requests:
https://example.com/.well-known/nostr.json?name=you
The answer must be JSON like this:
{
"names": {
"you": "<your public key in lowercase hex>"
},
"relays": {
"<your public key in lowercase hex>": ["wss://relay.example.com"]
}
}

relays is optional but recommended. If you want people to see just example.com, use the name _ (so _@example.com).
Common failures:
- npub instead of hex. The file must contain the 64-character hex key in lowercase, not the
npub1…form. - Wrong characters in the name. The part before
@may only usea-z,0-9,-,_and.. No capitals. - Redirects. The spec is strict: the endpoint must not redirect, and clients must ignore redirects. A host that sends
example.comtowww.example.com, or moves/.well-known/to another path, silently breaks verification. Put the file where the identifier points. - Missing CORS header. Web clients can only read the file if the server sends
Access-Control-Allow-Origin: *. Without it, the check fails in the browser and looks exactly like a missing file. - Bot protection blocking clients. Some hosts and firewalls answer real browsers but return 403 or a challenge page to other software. Verifiers and some clients are “other software”. The file loads when you open it, yet the check mark never appears.
Test it like a client would, not only in your browser:
curl -sI "https://example.com/.well-known/nostr.json?name=you"
curl -s -o /dev/null -w "%{http_code}\n" -A "Go-http-client/1.1" "https://example.com/.well-known/nostr.json?name=you"
The first should show 200 and access-control-allow-origin: * and no location: header. The second should also print 200. If it prints 403, ask your host to allow non-browser requests to /.well-known/.
4. Lightning address: make zaps actually land
The lud16 field holds a Lightning address such as you@wallet.example. (The older lud06 field holds a bech32 LNURL string. You only need one, and lud16 is easier to read and change.)
A Lightning address resolves to an LNURL-pay endpoint:
https://wallet.example/.well-known/lnurlp/you
For a payment to become a zap (with the ⚡ counter and a public receipt), that endpoint has to say it supports Nostr. You can check:
curl -s https://wallet.example/.well-known/lnurlp/you
Look for "allowsNostr": true and a "nostrPubkey". If those are missing, people can still pay you, but no zap receipt is created, so senders see nothing happen and assume it failed.
Common failures:
- The address has a typo, or belongs to a wallet account you closed.
- A fresh self-hosted node has no inbound liquidity, so it cannot receive yet.
- The sender’s app is the problem: on mobile, if no wallet is connected inside the client, it hands the invoice to whatever Lightning app the phone opens by default. Connecting a wallet in the client (usually via Nostr Wallet Connect) avoids that.
Test it properly. Ask a friend, or use a second account and wallet, to zap you 21 sats from two different clients. You want to see the sats arrive and the zap appear on the note in both clients. One client is not a test.
5. Publish the profile so people actually see it
Your profile is a replaceable event: kind 0. Clients show the newest version they can find. If you publish it to one relay, people who read other relays keep seeing the old one.
- Publish to your write relays (the ones in your
kind:10002relay list) and keep that list short: two to four is enough. - Also publish to purplepag.es. It collects profiles and relay lists, and many clients look there when they can’t find you elsewhere.
- Edit from one client, then check. A client holding an old copy of your profile can overwrite newer fields when you save. After any change, look at your profile in a second client before you assume it worked.
- Re-publish after host changes. If you move your images or change your Lightning address, the new kind 0 has to reach your relays, or the old links live on.
The ten-minute self-check

- Picture and banner load in two different clients and in a private browser window.
- Image URLs end in a SHA-256 hash, and each file exists on at least two Blossom servers.
- You have a
kind:10063server list (and, where your tools support it,imetafallbacks in your profile). name,display_nameand a three-line bio are set.- Your
nostr.jsonreturns 200 with your hex key, no redirect, andAccess-Control-Allow-Origin: *. - The same URL also returns 200 for a non-browser user agent.
- Your Lightning address resolves and its LNURL response shows
allowsNostr: trueand anostrPubkey. - A 21-sat test zap arrives and shows as a zap in two clients.
- Your newest kind 0 is on your write relays and on purplepag.es.
- You re-check all of the above once a month.
If every line is a yes, your profile works for the people who find it, not just for you.
If you would rather have someone go through it for you: dntry does a Profil-Check for 2,100 sats. You get five concrete improvements (picture, banner, bio, NIP-05, Lightning address) as a DM within 24 hours, and the 2,100 sats are credited in full if you later take the 21,000-sat profile pack. DM _@dntry.com to order. You sign any profile change yourself; your key never leaves you.
Write a comment