Card Not Generating on Bluesky

Why your link shows with no preview card in Bluesky posts

Likely causes

  1. OG tags rendered by JavaScript: CardyB fetches raw HTML only. If your tags are injected client-side by React, Vue, or similar, CardyB never sees them.
  2. WAF or CDN blocking the crawler: Cloudflare Bot Fight Mode, AWS WAF, and similar services often block CardyB because it crawls from cloud infrastructure with rotating IPs.
  3. “Invalid URL: host IP” error: Bluesky rejects URLs that resolve to private or reserved IP addresses (localhost, 10.x.x.x, 192.168.x.x) as a security measure. Domains with unusual DNS configurations can also hit this.
  4. robots.txt blocking: if BlueskyPreviewBot is disallowed, CardyB respects the restriction and returns nothing.

Diagnosis

  1. curl your URL and verify the OG tags are in the raw HTML, not injected after page load.
  2. Simulate a CardyB request:
curl -A "Mozilla/5.0 (compatible; Bluesky Cardyb/1.1; +mailto:support@bsky.app)" https://yoursite.com/page
  1. Check https://yoursite.com/robots.txt and make sure BlueskyPreviewBot isn’t blocked.
  2. Check your WAF/CDN logs for blocked requests from the CardyB user agent. Cloudflare users: Security > Events.
  3. Hit the CardyB API directly to see exactly what Bluesky gets:
curl "https://cardyb.bsky.app/v1/extract?url=https://yoursite.com/page"
  1. Verify your domain resolves to a public IP, not a private or reserved range.

WAF and CDN blocking

CardyB runs on cloud infrastructure, so its requests look like bot traffic to protection systems. Add an allow rule for the user agent:

  • Cloudflare: Security > WAF > Custom rules, skip bot checks for user agents containing Bluesky Cardyb
  • AWS WAF: add a user-agent-based allow rule to your bot control rule group

Third-party AT Protocol apps

If you’re building a Bluesky client or bot, the AT Protocol API does not auto-generate cards from URLs. Your app must handle the full pipeline: fetch the URL, parse OG tags, download and compress the image under 1 MB, upload the blob, and construct the app.bsky.embed.external record.

Testing your fix

Hit the CardyB API after making changes:

curl "https://cardyb.bsky.app/v1/extract?url=https://yoursite.com/page"

You should see JSON with your page’s title, description, and image URL. Then create a test post to confirm the card renders.