Blog18 min read
Extract website metadata and Open Graph tags at the edge
Deep HTMLRewriter guide for OG/meta extraction on Cloudflare Workers - vs Browser Rendering, JSON-LD, caching, link previews, and Metadata Extractor.
Link previews, SEO audits, and agent crawls often need title, description, canonical, and Open Graph tags. Fetching HTML and walking it with HTMLRewriter on a Worker is fast and cheaper than launching Browser Rendering for every URL.
The Metadata Extractor experiment returns those fields as JSON with validated http(s) input.
Cloudflare products in this pattern
| Product | Role | Docs |
|---|---|---|
| Workers | Fetch + API facade | Edge compute |
| HTMLRewriter | Streaming CSS-selector HTML parse | Runtime API |
| Fetch | Retrieve origin HTML | Fetch |
| Browser Rendering | Escalate when tags need JS | Headless Chrome |
| Cache API | Cache successful metadata JSON | Cache |
| KV / R2 | Longer-lived preview storage | Storage |
Fetch + rewrite vs headless Chrome
| Approach | Best when | Product |
|---|---|---|
fetch + HTMLRewriter | Tags exist in initial HTML | HTMLRewriter |
| Browser Rendering | Tags injected only after JS | Browser Rendering |
Most marketing sites and blogs still ship og:* in the first response. Start cheap; escalate only when fields are missing. Official HTMLRewriter guide: HTMLRewriter · Workers.
What to extract
A practical metadata payload:
title-<title>orog:titledescription- meta description orog:descriptioncanonical-rel=canonicalorog:urlimage-og:imagesiteName-og:site_name- Optional: Twitter card tags, theme color, robots meta
Normalize absolute image URLs against the page origin. Truncate oversized descriptions for UI cards. Prefer UTF-8 decoding awareness for international sites.
HTMLRewriter sketch
HTMLRewriter streams the response so you never buffer megabytes just to read a few tags:
rewriter.on('meta[property="og:title"]', {
element(el) {
title = el.getAttribute("content") ?? title;
},
});Handlers run as the HTML streams - see element handlers in the HTMLRewriter docs. The HTML Rewriter experiment isolates the API itself if you want a smaller learning surface.
Compose richer page APIs
| Goal | Experiment | Product |
|---|---|---|
| Core OG/meta | Metadata Extractor | HTMLRewriter |
| Broader structured JSON | Website to API | HTMLRewriter |
| LLM-friendly export | Website to llms.txt | Fetch + parse |
| JSON-LD entities | JSON-LD Extractor | HTMLRewriter / JSON |
| Visual fallback image | Screenshot API | Browser Rendering |
A link-preview product might call metadata first, then optionally screenshot when an image is missing.
Caching strategy
Metadata for a URL is often stable for hours:
- Build a cache key from canonical URL
caches.default.match(Cache API)- On MISS, fetch + rewrite, then
putwiths-maxage - For editorial previews, also store in KV with explicit purge on publish webhooks
Deploy and compare
- Read HTMLRewriter
- Deploy Metadata Extractor
- Point it at a blog post and a JS-heavy SPA
- If SPA tags are empty, retry with Browser Rendering scrape / screenshot
- Cache successful payloads
You get previews that stay cheap on the common path and only spend browser time when HTML is not enough - Workers as the vehicle, HTMLRewriter as the product capability.
Production checklist
- Validate URLs and block private destinations.
- Prefer HTMLRewriter first; escalate to Browser Rendering only on miss.
- Normalize absolute image URLs.
- Cache successful payloads.
- Respect robots/ToS for third-party targets.
- Store preview cards with explicit TTLs.
FAQ
Why is og:image empty on SPAs?
Client-rendered meta tags never appear in the first HTML. Use Browser Rendering or ask the site for SSR.
JSON-LD instead of OG?
Many sites expose Product/Article entities in JSON-LD - see JSON-LD Extractor. Use both when building rich previews.
Related experiments
These deployable references implement the patterns in this article. Open the docs for API details, then Deploy or clone the source.
- Website Metadata Extractor - Extract title, description, Open Graph, Twitter Card, and canonical URL from any webpage - SEO metadata API
- Website to API - Turn any webpage into structured JSON (title, headings, links, images) - HTML-to-API scraper for agents and apps
- Website to llms.txt - Convert any webpage into llms.txt format for LLM and AI-agent consumption - AI-readable site summary generator
- HTML Rewriter - Extract HTML stats and transform pages with Cloudflare HTMLRewriter - streaming HTML parse/transform at the edge
- JSON-LD Extractor - Extract Schema.org JSON-LD structured data from any webpage at the edge - rich results and SEO markup inspection
- Screenshot API - Capture website screenshots with Cloudflare Browser Rendering - full-page or viewport PNG/JPEG screenshot API