Skip to content

Free tool

Bluesky link facets tool

Computes real AT Protocol "facets" for a Bluesky post: byte-accurate ranges (byteStart/byteEnd, real UTF-8 byte offsets, not character indexes) for every link, hashtag and @mention in your text, in the documented app.bsky.richtext.facet format. Link and tag facets are fully computed and ready to use; a mention facet’s "did" field needs a live handle lookup this client-side tool cannot perform, so it is marked null.

  • @alice.bsky.socialmention

    byteStart 38, byteEnd 56 — did: null (resolve via com.atproto.identity.resolveHandle)

  • https://skedcast.comlink

    byteStart 64, byteEnd 84

  • #schedulingtag

    byteStart 85, byteEnd 96

Full record (text + facets)

{
  "text": "Scheduling posts with SkedCast — cc @alice.bsky.social, check https://skedcast.com #scheduling",
  "facets": [
    {
      "index": {
        "byteStart": 38,
        "byteEnd": 56
      },
      "features": [
        {
          "$type": "app.bsky.richtext.facet#mention",
          "did": null
        }
      ]
    },
    {
      "index": {
        "byteStart": 64,
        "byteEnd": 84
      },
      "features": [
        {
          "$type": "app.bsky.richtext.facet#link",
          "uri": "https://skedcast.com"
        }
      ]
    },
    {
      "index": {
        "byteStart": 85,
        "byteEnd": 96
      },
      "features": [
        {
          "$type": "app.bsky.richtext.facet#tag",
          "tag": "scheduling"
        }
      ]
    }
  ]
}

How to use the Bluesky facets tool

  1. Type your post text. Include any links, @handle mentions or #hashtags exactly as you’d post them.
  2. Review the detected facets. Each link, mention and hashtag is listed with its real byte offsets.
  3. Copy a facet or the full record. Copy one facet’s JSON, or the whole text-plus-facets record at once.
  4. Resolve mention DIDs before posting. Use com.atproto.identity.resolveHandle to fill in the real DID for any mention.

Worked examples

A multi-byte character shifts the byte offset

"Check café https://example.com" — the link starts at byte 12, not character index 11, because "café " is 5 characters but 6 UTF-8 bytes (é takes 2 bytes).

A link’s fragment is not a separate hashtag

"See https://example.com/page#section here" produces exactly one link facet for the whole URL — the "#section" inside it is never reported as a separate tag facet.

Bluesky facets tool FAQ

Why does Bluesky use byte offsets instead of character positions?
Because post text is stored as UTF-8 bytes on the network, and the AT Protocol’s own facet format is documented to index by byte offset, not character count.
Why is the mention facet’s "did" field null?
Resolving a handle to its real DID needs a live network call to com.atproto.identity.resolveHandle, which this client-side tool does not make.
Can I post directly from this tool?
No — this only computes the real facet data; you still post through Bluesky’s own app or API using the generated record.
Does this tool call the Bluesky API?
No — everything is computed locally from the text you type, using real UTF-8 byte-length math, with no network request made.
What if two facets overlap, like a link containing a hashtag-shaped fragment?
Links take priority — a hashtag or mention pattern found inside an already-matched link’s character range is never reported as its own separate facet.
Is this the official Bluesky client?
No — it is an independent tool that implements the real, documented AT Protocol facet format for developers testing or building their own integration.

Ready to broadcast everywhere?

Sign up free — no credit card. You land on the Free plan, and you can start a one-time 7-day Studio trial from your workspace whenever you are ready. Connect your first accounts, import a batch, and watch one post fan out across every platform.