Link Preview API [$0.99/1K💰] | OG + JSON-LD
Pricing
from $0.94 / 1,000 link previews
Link Preview API [$0.99/1K💰] | OG + JSON-LD
Turn any URL into 42 metadata fields - Open Graph, Twitter Cards, JSON-LD, oEmbed, feeds, favicon, canonical and publish dates - over plain HTTP. Batch runs, a Standby REST API and MCP, with SSRF protection built in.
Pricing
from $0.94 / 1,000 link previews
Rating
0.0
(0)
Developer
Ahmed Jasarevic
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
a month ago
Last modified
Categories
Features
Share
Link Preview API
Turn any URL into 49 structured metadata fields — Open Graph, Twitter Cards, JSON-LD, oEmbed, favicons, feeds, hreflang, canonical and publish dates — as a batch Apify run, a Standby REST API, or a call from an AI agent over MCP.
- 49 fields, not 10. Title, description, images, site name, type, canonical, favicon, apple-touch icon, manifest, RSS/Atom feeds, hreflang alternates, language, author, publisher, published and modified times, robots, theme colour, Twitter card details, Schema.org types, JSON-LD and oEmbed.
- Two ways to call it. Batch it as a normal Apify run, or point your app at the Standby HTTP API —
GET /v1/preview?url=for one URL,POST /v1/unfurlfor up to 100. - SSRF protection built in. Cloud metadata hosts,
localhost,.localand private IP ranges are refused by default, including after DNS resolution and across redirects. Gate it off withallowPrivateNetworkif you genuinely need internal URLs. - No third-party API key. No Microlink, no OpenGraph.io, no per-request vendor bill.
- About 2× cheaper than the verified Apify alternative at
$0.99per 1,000 previews on the FREE tier, against$2.00per 1,000.
Main Use Cases
- Bulk link unfurling — enrich up to 100 URLs per
POST /v1/unfurlcall, or a whole list per Apify run - Slack and Discord-style preview cards — map
title,description,image,siteNameandfaviconinto your own markup - Open Graph auditing — check whether your own pages expose complete
og:tags, canonical URLs and images - JSON-LD and Schema.org extraction — pull structured product, article, recipe and organisation data
- CRM and lead enrichment — attach page titles, descriptions and images to company or contact records
- RSS feed and hreflang detection — discover feeds and language alternates from any page
- URL metadata for AI agents — expose a metadata endpoint agents can call via MCP instead of fetching raw HTML
How It Works
- Each URL is validated and screened against the SSRF guard. Blocked hosts and private addresses are refused before any request is made, and re-checked after DNS resolution and at each redirect hop.
- The page is fetched over HTTP with retries, a configurable timeout, and redirect following. Response HTML is size-capped.
- Metadata is parsed in priority order: Open Graph, then Twitter Card tags, then HTML fallbacks (
<title>, meta description, canonical link, favicon), then platform-specific oEmbed endpoints whenfetchOembedis on. includeJsonLdextracts everyapplication/ld+jsonblock, withschemaTypesgiving the detected Schema.org types.includeRawTagsadds the raw meta tags map for auditing work.- An optional TTL cache (
cacheTtlSecs,useKvCache) avoids refetching unchanged URLs.
Two dataset views are available: overview for a quick scan and details for the full record.
Honest limitation: this Actor does not execute client-side JavaScript. It reads the HTML returned by the initial HTTP response plus oEmbed endpoints. Client-rendered single-page apps often return minimal metadata unless they also expose server-rendered
og:tags or an oEmbed endpoint. That is the same trade-off the popular open-source unfurl libraries make.
Fetch Link Metadata Without a Paid Preview API or a Third-Party Key
Commercial preview APIs solve the hard parts — proxy tiers, JavaScript rendering, edge caching — and charge per request accordingly. If you only need the metadata tags a page already publishes, that is the expensive part you are paying for.
This Actor reads the published tags directly, over plain HTTP, with no vendor key and no per-request bill. For the common case — building preview cards, auditing your own pages, enriching records — that is enough. The trade-off is documented above: no client-side JavaScript rendering.
Input
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
urls | array | no | — | URLs to preview. Bare strings or { "url": "..." } objects are both accepted. |
maxItems | integer | no | 0 | Limit how many URLs are processed. 0 (or any non-positive value) processes all of them. |
maxConcurrency | integer | no | 10 | Parallel fetches. |
requestTimeoutSecs | integer | no | 20 | Per-request timeout in seconds. |
maxRetries | integer | no | 1 | Retries per URL on transient failures. |
includeJsonLd | boolean | no | true | Extract JSON-LD blocks and detected Schema.org types. |
includeRawTags | boolean | no | false | Include the raw meta tags map. Useful for audits; increases row size. |
fetchOembed | boolean | no | true | Fall back to platform oEmbed endpoints when a page has weak or no tags. |
cacheTtlSecs | integer | no | 3600 | Cache time-to-live in seconds. |
useKvCache | boolean | no | false | Persist the cache in a key-value store so it survives across runs. |
allowPrivateNetwork | boolean | no | false | Permit localhost, .local and private IP targets. Off by default for SSRF safety. |
Output
One row per URL (49 fields):
url, finalUrl, domain, ok, status, error, contentType, responseTimeMs, attempts, truncated, htmlBytes, charset, title, description, image, images, siteName, type, canonical, favicon, appleTouchIcon, manifestUrl, feedUrl, feeds, hreflang, language, author, publisher, publishedTime, modifiedTime, robots, themeColor, twitterCard, twitterSite, twitterCreator, openGraph, twitter, schemaTypes, jsonLd, metaTags, oembed, oembedRaw, oembedEndpoint, redirectChain, isShortened, cleanUrl, excerpt, cacheHit, fetchedAt
Every URL produces a row even when it fails. Check ok first: on failure error explains why and status carries the HTTP status where one was received. A blocked-by-SSRF URL returns ok: false with an error such as Private addresses are not allowed — that is a deliberate refusal, not a network fault.
Example Input
{"urls": ["https://github.com","https://www.theverge.com/2026/1/28/some-article","https://news.ycombinator.com"],"includeJsonLd": true,"fetchOembed": true,"includeRawTags": false,"cacheTtlSecs": 3600}
Example Output
{"url": "https://www.theverge.com/2026/1/28/some-article","finalUrl": "https://www.theverge.com/2026/1/28/some-article","domain": "www.theverge.com","ok": true,"status": 200,"error": null,"contentType": "text/html; charset=utf-8","responseTimeMs": 412,"attempts": 1,"truncated": false,"htmlBytes": 184213,"charset": "utf-8","title": "The chip supply question nobody wants to answer","description": "Fabrication capacity, not design, is now the bottleneck for advanced packaging — and the industry has been slow to say so.","image": "https://www.theverge.com/hero-chip.jpg","images": [{ "url": "https://www.theverge.com/hero-chip.jpg", "width": 1200, "height": 628, "alt": "Advanced packaging wafer" },{ "url": "https://www.theverge.com/hero-chip-thumb.jpg", "width": 600, "height": 314, "alt": null }],"siteName": "The Verge","type": "article","canonical": "https://www.theverge.com/2026/1/28/some-article","favicon": "https://www.theverge.com/favicon.ico","appleTouchIcon": "https://www.theverge.com/apple-touch-icon.png","manifestUrl": "https://www.theverge.com/manifest.json","feedUrl": "https://www.theverge.com/rss/index.xml","feeds": [{ "url": "https://www.theverge.com/rss/index.xml", "type": "application/rss+xml", "title": "The Verge" }],"hreflang": [{ "lang": "en-US", "href": "https://www.theverge.com/2026/1/28/some-article" },{ "lang": "de", "href": "https://www.theverge.com/de/2026/1/28/some-article" }],"language": "en-US","author": "A. Reporter","publisher": "Vox Media","publishedTime": "2026-01-28T14:02:11Z","modifiedTime": "2026-01-28T16:40:03Z","robots": "max-image-preview:large, noarchive","themeColor": "#000000","twitterCard": "summary_large_image","twitterSite": "@theverge","twitterCreator": "@areporter","openGraph": {"og:title": "The chip supply question nobody wants to answer","og:description": "Fabrication capacity, not design, is now the bottleneck for advanced packaging.","og:image": "https://www.theverge.com/hero-chip.jpg","og:type": "article","og:site_name": "The Verge"},"twitter": {"twitter:card": "summary_large_image","twitter:site": "@theverge","twitter:title": "The chip supply question nobody wants to answer"},"schemaTypes": ["NewsArticle", "Article"],"jsonLd": [{"@context": "https://schema.org","@type": "NewsArticle","headline": "The chip supply question nobody wants to answer","datePublished": "2026-01-28T14:02:11Z","author": { "@type": "Person", "name": "A. Reporter" },"publisher": { "@type": "Organization", "name": "Vox Media" }}],"metaTags": null,"oembed": null,"oembedRaw": null,"oembedEndpoint": null,"redirectChain": [],"isShortened": false,"cleanUrl": "https://www.theverge.com/2026/1/28/some-article","excerpt": "Fabrication capacity, not design, is now the bottleneck for advanced packaging — and the industry has been slow to say so.","cacheHit": false,"fetchedAt": "2026-02-11T11:22:08.415Z"}
Standby REST API
This Actor runs a container web server, so you can call it directly over HTTP without starting an Apify run:
GET / health and service info (JSON)GET /health plain-text liveness probe -> okGET /v1/preview?url=<encoded-url> one URLPOST /v1/unfurl {"urls": [...]} up to 100 URLs per request
The batch endpoint caps at 100 URLs per request. CORS preflight (OPTIONS) is handled, so browser clients can call it. The full OpenAPI description is in .actor/web_server_openapi.json and renders as the Endpoints tab in Apify Console.
Pricing
Pay-per-event at $0.99 per 1,000 previews on the FREE tier, with a low per-run starting cost. Each URL fetched counts as one event, including ones that fail or are blocked — blocked requests are refused locally but are still counted.
Integrations & Automation
- Standby REST API — point any app at the container URL for single or batch (100-URL) unfurling.
- Apify API — schedule batch enrichment of large URL lists and read the dataset.
- Schedules — re-audit your own pages daily for new pages, broken images or regressed tags.
- Webhooks — fire downstream enrichment when a batch completes.
- MCP — callable by AI agents through the Apify MCP server, so an agent can resolve a URL to metadata with one tool call.
Related Actors
ahmed_jasarevic/preply-scraper— extract structured profile data from tutor URLs after resolving their preview metadataahmed_jasarevic/goodreads-scraper— extract book metadata and review text from Goodreads URLs
FAQ
Why not just use Microlink or OpenGraph.io?
Those solve JavaScript rendering and proxy routing, which cost extra per request. If you only need the metadata a page already publishes, this Actor gives you the same fields over plain HTTP with no vendor account or API key, at roughly half the per-preview price of the comparable Apify Actor. If you genuinely need rendered metadata for client-rendered SPAs, those tools are the better fit — this Actor does not run JavaScript.
Why is my link preview empty for some sites?
The most common cause is a client-rendered single-page app: the initial HTML response is an empty shell, so there are no og: tags to read. Check ok, status and htmlBytes — a tiny htmlBytes with ok: true is the signature of that case. Enabling fetchOembed helps on platforms that publish an oEmbed endpoint.
What is the difference between image and images?
image is the single best image (Open Graph preferred, then Twitter Card). images is the full array with width, height and alt for each. Use image for a card and images when you want to pick a size.
Why did a URL fail with "Private addresses are not allowed"?
The SSRF guard refused it. localhost, .local, private and link-local IP ranges, and cloud metadata hostnames are blocked by default, and the check runs again after DNS resolution and after each redirect. This is intentional — it prevents a user-supplied URL from reaching internal infrastructure. Set allowPrivateNetwork: true only if you are deliberately previewing internal hosts.
What does cacheHit mean, and when should I use useKvCache?
cacheHit: true means the result came from the cache rather than a fresh fetch. useKvCache: false keeps the cache in memory for the duration of the run; setting it to true persists the cache to a key-value store so repeated runs reuse metadata until cacheTtlSecs expires.
Can I extract JSON-LD and Schema.org types?
Yes — includeJsonLd defaults to true. jsonLd holds each parsed application/ld+json block and schemaTypes gives the detected Schema.org types such as NewsArticle or Product.
Do I need an API key?
No. There is no third-party account or key involved.
What are alternatives to this actor?
Commercial APIs such as Microlink and OpenGraph.io (which add rendering and proxies), free-tier tools like api.linkmetadata.com (rate-limited to 20 requests per 10 seconds per IP), and open-source libraries such as jacktuck/unfurl — which also does not execute JavaScript. On the Apify Store the comparable Actor is technicaldost/link-preview-api, which returns roughly a third as many fields and costs about twice as much per preview.
For AI Agents & LLM Apps
Purpose: returns one row per URL with normalized Open Graph, Twitter Card, JSON-LD, oEmbed, feed, hreflang and icon metadata, plus fetch diagnostics.
Minimal working input — smallest input that produces a valid run:
{ "urls": ["https://apify.com"] }
Batch audit variant:
{"urls": ["https://example.com/a", "https://example.com/b", "https://example.com/c"],"maxItems": 100,"includeJsonLd": true,"includeRawTags": true,"fetchOembed": true,"maxConcurrency": 5}
Output fields — url, finalUrl, domain, ok, status, error, contentType, responseTimeMs, attempts, truncated, htmlBytes, charset, title, description, image, images, siteName, type, canonical, favicon, appleTouchIcon, manifestUrl, feedUrl, feeds, hreflang, language, author, publisher, publishedTime, modifiedTime, robots, themeColor, twitterCard, twitterSite, twitterCreator, openGraph, twitter, schemaTypes, jsonLd, metaTags, oembed, oembedRaw, oembedEndpoint, redirectChain, isShortened, cleanUrl, excerpt, cacheHit, fetchedAt
Behaviors an agent should know
urlsaccepts both bare strings and{ "url": "..." }objects. Either form works.maxItemsdefaults to0, which means process ALL URLs. It only truncates when it is greater than zero. SettingmaxItems: 1does not mean "one URL" — it means "the first one".- Every URL produces a row, including failures. Check
okbefore trusting the metadata fields; on failureerrorgives the reason andstatusmay benullwhen no response was received. - A blocked URL is not a bug. SSRF refusals return
ok: falsewith an error such asPrivate addresses are not allowed. Do not retry these. - No JavaScript is executed. Client-rendered SPAs return minimal metadata. Diagnose with
htmlBytes(very small means an empty shell) andok: true. includeRawTagsdefaults tofalse. Turn it on for tag auditing; it materially increases row size and billed dataset size.- Use
imagefor the primary preview image;imagesis the full array with dimensions and alt text. fetchOembed(defaulttrue) adds a network round trip per weak-tag URL, so it slows runs on pages with no tags.- The Standby batch endpoint
POST /v1/unfurlaccepts at most 100 URLs per request;GET /v1/preview?url=handles one. - Set
allowPrivateNetwork: trueonly when you intentionally need internal URLs — it disables the SSRF guard. - Two dataset views exist:
overviewanddetails.
Billing: pay-per-event — $0.99 per 1,000 previews on the FREE tier. Every URL processed counts, including failures and SSRF blocks.
SEO Keywords
link preview api, open graph api, url metadata api, link unfurl, unfurl url api, open graph extractor, twitter card metadata, json-ld extractor, oembed api, extract title description image from url, bulk link preview, link preview javascript, url unfurling node, fetch favicon url, schema.org extraction api, rss feed detection api, hreflang extraction, slack unfurl bot api, discord link unfurl, link preview microservice, ssrf protection url fetcher, open graph alternative, microlink alternative, unfurl.js alternative, url metadata for ai agents