Build link previews in 5 minutes
When someone pastes a URL into your chat app, bookmark tool, or CMS, you usually want a small card: title, description, and an image. Parsing Open Graph tags yourself is tedious and easy to get wrong (redirects, relative image URLs, favicon fallbacks).
This walkthrough builds a minimal link-preview helper that calls a metadata API over HTTPS and renders a card. We’ll use the public URL Metadata & Open Graph Extractor on RapidAPI:
https://rapidapi.com/evan-DewNPsuYp/api/url-metadata-open-graph-extractor
You need a free RapidAPI account and an API key from the dashboard. The listing’s free tier is enough to try this locally.
What you get back
One GET request with a url query parameter returns JSON roughly like:
-
title,description,image,favicon -
openGraph/twitterobjects -
canonical,siteName,jsonLdwhen present
The service fetches public HTML only (no login walls, no headless browser). SPA shells that don’t put meta tags in the initial HTML may return sparse results — that’s expected for v1.
1. Grab a key
- Open the listing above and subscribe to a plan (start with Basic/Free if available).
- Copy your
X-RapidAPI-Keyfrom https://rapidapi.com/developer/dashboard . - Host header for this API (from the public page):
url-metadata-open-graph-extractor.p.rapidapi.com
Store the key in an environment variable — never commit it.
export RAPIDAPI_KEY='your-key-here'
2. One request with curl
curl --request GET \
--url 'https://url-metadata-open-graph-extractor.p.rapidapi.com/v1/metadata?url=https%3A%2F%2Fwww.wikipedia.org%2F' \
--header "X-RapidAPI-Key: $RAPIDAPI_KEY" \
--header 'X-RapidAPI-Host: url-metadata-open-graph-extractor.p.rapidapi.com'
You should see JSON with "ok": true, a title like "Wikipedia", a description, and an image URL pointing at the Wikipedia logo.
3. Tiny Node helper
// preview.mjs
const HOST = "url-metadata-open-graph-extractor.p.rapidapi.com";
export async function fetchLinkPreview(targetUrl) {
const endpoint = new URL(`https://${HOST}/v1/metadata`);
endpoint.searchParams.set("url", targetUrl);
const res = await fetch(endpoint, {
headers: {
"X-RapidAPI-Key": process.env.RAPIDAPI_KEY,
"X-RapidAPI-Host": HOST,
},
});
const data = await res.json();
if (!res.ok || !data.ok) {
const err = new Error(data.error || `HTTP ${res.status}`);
err.code = data.code;
throw err;
}
return {
title: data.title,
description: data.description,
image: data.image,
favicon: data.favicon,
url: data.finalUrl || data.url,
};
}
// demo
const preview = await fetchLinkPreview("https://www.wikipedia.org/");
console.log(preview);
Run with:
node preview.mjs
4. Render a card (plain HTML)
function renderCard(p) {
const img = p.image
? `<img src="${p.image}" alt="" width="120" height="120" />`
: "";
return `
<article class="link-card">
${img}
<div>
<a href="${p.url}" rel="noopener noreferrer">${p.title || p.url}</a>
<p>${p.description || ""}</p>
</div>
</article>`;
}
Wire fetchLinkPreview into your backend route so the RapidAPI key never ships to the browser.
Practical tips
-
Encode the URL. Always
encodeURIComponent/searchParams.setthe target. - Timeouts. Upstream sites can be slow; set a client timeout (e.g. 15–30s) and show a fallback card.
-
Errors. Watch for
ssrf_blocked(private IPs),unsupported_media, andupstream_error. Surface a generic “preview unavailable” UI. - Caching. Cache successful previews by normalized URL for a few hours to stay inside your monthly quota.
What’s next
- Add a small in-memory or Redis cache keyed by URL.
- Fall back to the hostname when
titleis null. - If you also need the page body as Markdown for RAG, see the companion API: URL to Markdown (LLM-ready).
That’s it — a working link preview path in a few minutes without maintaining your own HTML meta parser.
Top comments (0)