> ## Documentation Index
> Fetch the complete documentation index at: https://bun-1dd33a4e-farm-de84d354-pm-sbom.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Extract social share images and Open Graph tags

## Extract social share images and Open Graph tags

Bun's [HTMLRewriter](/runtime/html-rewriter) API extracts social share images and Open Graph metadata from HTML by matching CSS selectors against the elements, text, and attributes you want to process. Use it to build link previews, social media cards, or web scrapers.

```ts extract-social-meta.ts icon="https://mintcdn.com/bun-1dd33a4e-farm-de84d354-pm-sbom/IPGjipyt_DGwYrQc/icons/typescript.svg?fit=max&auto=format&n=IPGjipyt_DGwYrQc&q=85&s=4448657ec154e63e3a095030af59c903" theme={"theme":{"light":"github-light","dark":"dracula"}}
interface SocialMetadata {
  title?: string;
  description?: string;
  image?: string;
  url?: string;
  site_name?: string;
  type?: string;
}

async function extractSocialMetadata(url: string): Promise<SocialMetadata> {
  const metadata: SocialMetadata = {};
  const response = await fetch(url);

  const rewriter = new HTMLRewriter()
    // Extract Open Graph meta tags
    .on('meta[property^="og:"]', {
      element(el) {
        const property = el.getAttribute("property");
        const content = el.getAttribute("content");
        if (property && content) {
          // Convert "og:image" to "image" etc.
          const key = property.replace("og:", "") as keyof SocialMetadata;
          metadata[key] = content;
        }
      },
    })
    // Extract Twitter Card meta tags as fallback
    .on('meta[name^="twitter:"]', {
      element(el) {
        const name = el.getAttribute("name");
        const content = el.getAttribute("content");
        if (name && content) {
          const key = name.replace("twitter:", "") as keyof SocialMetadata;
          // Only use Twitter Card data if nothing has set this key yet (OG tags always overwrite it)
          if (!metadata[key]) {
            metadata[key] = content;
          }
        }
      },
    })
    // Fallback to regular meta tags
    .on('meta[name="description"]', {
      element(el) {
        const content = el.getAttribute("content");
        if (content && !metadata.description) {
          metadata.description = content;
        }
      },
    })
    // Fallback to title tag
    .on("title", {
      text(text) {
        if (!metadata.title) {
          metadata.title = text.text;
        }
      },
    });

  // Process the response
  await rewriter.transform(response).blob();

  // Convert relative image URLs to absolute
  if (metadata.image && !metadata.image.startsWith("http")) {
    try {
      metadata.image = new URL(metadata.image, url).href;
    } catch {
      // Keep the original URL if parsing fails
    }
  }

  return metadata;
}
```

```ts Example Usage icon="https://mintcdn.com/bun-1dd33a4e-farm-de84d354-pm-sbom/IPGjipyt_DGwYrQc/icons/typescript.svg?fit=max&auto=format&n=IPGjipyt_DGwYrQc&q=85&s=4448657ec154e63e3a095030af59c903" theme={"theme":{"light":"github-light","dark":"dracula"}}
// Example usage
const metadata = await extractSocialMetadata("https://bun.com");
console.log(metadata);
// {
//   title: "Bun — A fast all-in-one JavaScript runtime",
//   description: "Bundle, install, and run JavaScript &amp; TypeScript — all in Bun. Bun is a fast JavaScript runtime &amp; toolkit with a bundler, test runner, and npm-compatible package manager built in.",
//   image: "https://bun.com/share_v4.png",
//   type: "website",
//   ...
// }
```
