Bluesky Link Preview Checker
See the Bluesky link preview your URL gets before you post it, and find out why a card is missing. It asks the same card service the Bluesky app uses.
Why a Bluesky link preview is not working
The Bluesky app builds a link card only if its card service, cardyb.bsky.app, can read your page's title, description and image. It fails when the page blocks the fetcher, returns an error, or adds its tags with JavaScript. Posts sent by an API or automation get no card unless the sender attaches one.
How a Bluesky link card is made
A Bluesky link preview is not generated when someone views the post. It is built once, by the app that creates the post, and stored inside the post record.
- You paste a link into the composer. The Bluesky app sends it to
cardyb.bsky.app/v1/extract, which fetches your page and returns the title, description and image it found. - The app downloads that image, resizes it to fit the thumbnail limit and uploads it to your account as a blob.
- When you post, the record carries an
app.bsky.embed.externalembed withuri,title,descriptionandthumb. The lexicon capsthumbat 1,000,000 bytes.
Posts from APIs and automations
Because the card lives in the record, anything that posts through the API (a script, a bot or an automation tool) has to do those three steps itself. If it sends only text, there is no card, and without a link facet the URL is not clickable either. See why links from Make.com are not clickable on Bluesky.Common reasons a Bluesky link preview is missing
| What you see | Likely cause | Fix |
|---|---|---|
| No card at all | The page returned 403, 404 or 5xx to the card fetcher, or timed out | Make the page public and fast. Allow the fetcher through your firewall or bot protection. |
| Card titled "Just a moment" or similar | A challenge page from bot protection was read instead of your page | Add a rule that lets link preview fetchers past the challenge. |
| Card with the wrong or empty title | Tags are added by JavaScript, so the raw HTML has none | Render og:title and og:description on the server. Check with View Source. |
| Card with no image | No og:image, a relative image path, or an image that does not load | Use an absolute HTTPS og:image URL that returns an image file. |
| No card on posts from a script or Make.com | The sender did not attach an app.bsky.embed.external embed | Build the embed in your code, or post the link from the Bluesky app. |
| Old posts still show the old card | Cards are stored in the post when it is created | Fixes apply to new posts only. |
The tags to have in your page's server HTML: og:title, og:description and og:image. The same tags drive previews on X and LinkedIn, so the X Card Validator and the Link Preview Checker help too.
Schedule Bluesky posts with clickable links
OpenTweet sends link facets with every Bluesky post, so your URLs are clickable, and schedules the same post to X and LinkedIn from one draft or one API call.
To be clear: OpenTweet does not attach link cards to Bluesky posts today. Links appear as clickable text.
7-day free trial. Link posts are included from the Advanced plan at $29/mo.
Bluesky Link Preview FAQ
Why is my Bluesky link preview not working?
Either the card service could not read your page, or the post was sent without a card. The Bluesky app builds a card only when cardyb.bsky.app returns data for the URL. It fails when the page blocks the fetcher, returns an error, or has its tags added by JavaScript. Posts sent by an API, Make.com or a script get no card unless the sender builds one.
How does Bluesky make a link card?
While you write a post, the Bluesky app sends the URL to cardyb.bsky.app, which reads the page title, description and image. The app downloads that image, resizes it, uploads it to your account as a blob and saves everything in the post as an app.bsky.embed.external embed with uri, title, description and thumb.
What size should the image for a Bluesky link card be?
The app.bsky.embed.external lexicon caps the card thumbnail at 1,000,000 bytes. The Bluesky app resizes the image before uploading it, so a larger og:image still works in the app. If you build the embed yourself through the API, shrink the image below that limit before you upload it.
Why do posts from Make.com, an API or a script have no link card?
Because the card is part of the post record, not something Bluesky adds later. The sender has to fetch the page data, upload the thumbnail and attach an app.bsky.embed.external embed. Plain text with a URL in it gets no card, and without a link facet the URL is not even clickable.
I fixed my tags. Will old posts show the new card?
No. The title, description and thumbnail are stored inside each post when it is created, so changing your page later does not change cards that already exist. New posts pick up the fixed tags.
Does a link count toward the Bluesky character limit?
Yes. Through the API a link counts at its full length toward the 300 grapheme limit. The bsky.app composer only shortens how the link is displayed. The card itself does not count.
Does OpenTweet add link cards to Bluesky posts?
Not today. OpenTweet makes every link in a Bluesky post clickable by sending link facets, and it schedules the same post to X and LinkedIn. It does not attach a link card embed to Bluesky posts, so a scheduled Bluesky post shows your link as clickable text.
Is this checker free, and what does it contact?
It is free with no signup. It runs in your browser and only talks to cardyb.bsky.app, the public card service the Bluesky app uses. It does not log in to Bluesky and does not post anything.
Related tools and guides
Link Preview Checker
Compare how one link previews on X, LinkedIn and Bluesky.
LinkedIn Post Inspector Alternative
See the card LinkedIn builds for a link, without logging in.
X Card Validator
Check twitter:card and Open Graph tags for X link previews.
Bluesky Character Counter
Count graphemes and bytes against the 300 limit.
Does a link count on Bluesky?
How links count toward the 300 character limit.
Make.com Bluesky links not clickable
Why automated posts need link facets, and two fixes.