Last updated: September 2026
Why does my Bluesky custom domain handle say Invalid Handle?
Because Bluesky could not confirm that your domain points to your account. Usually the _atproto TXT record sits at the wrong host or is missing its did= prefix. Other causes: two conflicting records, DNS still propagating, a DID mismatch, or a well-known file serving the wrong content.
Each one has a quick check. Start with the handle checker, or run the two commands below yourself.
What Bluesky checks
A domain handle is valid when two things agree. The domain has to point to your DID, either through a DNS TXT record at _atproto.<handle> with the value did=<DID>, or through a file at https://<handle>/.well-known/atproto-did. And your DID document has to point back to the handle. The atproto spec says a handle should not be trusted until both directions are confirmed. Source: the atproto handle specification.
Break either direction and the handle shows as invalid. That can happen long after it first worked: a DNS migration that drops the TXT record is enough.
The six causes and their fixes
The TXT record is at the wrong host
What it looks like: You typed _atproto.example.com into a DNS panel that appends your domain, so the record actually lives at _atproto.example.com.example.com.
Fix: Set the host to _atproto only. For a subdomain handle like alice.example.com, use _atproto.alice.
The did= prefix is missing
What it looks like: The value is did:plc:abc123 on its own. The spec says records without the did= prefix are ignored.
Fix: Set the value to did=did:plc:abc123, with your own DID. Yes, did appears twice.
More than one _atproto TXT record
What it looks like: An old record from a previous account or an earlier attempt is still there, pointing to a different DID.
Fix: Keep one record with your current DID and delete the rest.
DNS has not propagated yet
What it looks like: The record is correct in your panel but dig returns nothing, or returns the old value.
Fix: Wait, then check again. If your domain uses a different DNS host from your registrar, such as Cloudflare, the record has to be added there.
The DID does not match
What it looks like: The record points to a DID that is not your account, often copied from another account, or your DID document lists a different handle.
Fix: Copy the DID Bluesky shows for your account into the record, then set the handle again from the app so both directions agree.
The well-known file returns the wrong content
What it looks like: https://example.com/.well-known/atproto-did returns an HTML page, a 404, a did= prefix, or something other than the bare DID.
Fix: Serve the bare DID as plain text with a 2xx status and Content-Type: text/plain. No prefix, no markup.
The most common one
Many DNS panels add your domain to whatever you type in the host field. Type_atproto.example.com there and the record you create is _atproto.example.com.example.com. The panel looks right, the lookup finds nothing. Type _atproto alone.Check it yourself in two commands
Replace example.com with your handle. You only need one of the two methods to work.
# DNS method: expect exactly one line, starting with "did="
dig TXT _atproto.example.com +short
# Well-known method: expect a 2xx, text/plain, and only the DID
curl -i https://example.com/.well-known/atproto-didA correct DNS answer is a single line like "did=did:plc:abc123". No output means the record is at a different host or has not propagated. Two lines with different DIDs means cause three. A correct well-known answer is the bare DID and nothing else.
Then check the other direction. For a did:plc account, the DID document is public:
# alsoKnownAs should list at://example.com
curl https://plc.directory/did:plc:abc123If alsoKnownAs lists a different handle, set your handle again from the Bluesky app once the DNS record is correct. The Bluesky handle checker runs all three checks and tells you which one fails.
Setting it up from scratch
- In the Bluesky app, choose to use your own domain as your handle. It shows the exact record to add, including your DID.
- At whichever company hosts your DNS, which may not be your registrar, add a TXT record with host
_atprotoand valuedid=followed by your DID. - Remove any other
_atprotoTXT record on the same name. - Wait a few minutes, confirm with
dig, then press Verify DNS Record in the app.
Bluesky's own walkthrough covers the same steps, including the note that a DNS host like Cloudflare is where the record goes, not the original registrar. Source: Bluesky, "How to verify your Bluesky account".
Custom domains and OpenTweet
OpenTweet connects Bluesky over atproto OAuth, with no API key and no App Password. OAuth resolves your server from your handle, so a custom-domain handle connects the same way as a bsky.social one once it is valid. It is the same mechanism that lets self-hosted PDS accounts connect.
Resolution depends on the handle, so fix the Invalid Handle before you connect. After that, posts go to X and Bluesky from one draft or one API call, as covered in posting to X and Bluesky at the same time.
7-day free trial. Cancel anytime.
Frequently asked questions
Why does my Bluesky custom domain handle say Invalid Handle?
Because the domain no longer proves it belongs to your account. Bluesky checks that the domain points to your DID, through a DNS TXT record at _atproto.<handle> or a file at /.well-known/atproto-did, and that your DID points back to the domain. If either check fails, the handle shows as invalid.
What should the _atproto TXT record look like?
The host is _atproto followed by your handle, so _atproto.example.com for the handle example.com. The value is did= followed by your full DID, for example did=did:plc:abc123. In DNS panels that add your domain automatically, type only _atproto in the host field.
How long does DNS take to propagate for a Bluesky handle?
Bluesky's own guide says to wait a couple of minutes after adding the record. If your provider uses a long TTL, or you recently changed nameservers, it can take longer. Check the record with dig before assuming it is wrong.
Can I have two _atproto TXT records?
Not with different DIDs. The atproto handle spec says resolution should fail when multiple valid records point to different DIDs. Delete the old one, for example a record left from a previous account.
Does a custom domain handle work with OpenTweet?
Yes, once it is valid. OpenTweet connects Bluesky over atproto OAuth, which resolves your server from your handle, so a custom-domain handle connects like any other. Fix the Invalid Handle first, then connect.
Keep exploring
A valid handle is all OAuth needs to find your account, on any domain.
Bluesky handle checker
Checks the TXT record, the well-known file and the DID in one go, and says which one fails.
Cross-posting from a self-hosted PDS
Why handle resolution is what lets any server, and any domain, connect.
Post to X and Bluesky at once
Three routes, the limits that differ, and one curl that does both.
Do I have to paste a Bluesky password?
No. What atproto OAuth grants instead of an App Password.
How to cross-post to Bluesky
Connecting your handle and sending the first post to both networks.
Bluesky scheduler
Schedule Bluesky posts and threads, custom-domain handles included.
Cross-posting to X and Bluesky
One draft, a native post on each network, and a per-network result.
Your domain, your handle, one draft
Bluesky over atproto OAuth on every plan, X in the same call. From $11.99 a month.
7-day free trial. Cancel anytime.