TL;DR: Starting in Firefox version 142, Mozilla released a “Link Previews” feature whose main purpose is to push AI onto its users.
While the feature is problematic, commenters post pointed out that some previews are helpful – e.g. on Wikipedia, where a preview will appear when people hover over a wiki-linked page.

Other commenters pondered about some minimal way to replicate this elsewhere, and it seemed to be worth investigation. Read on as I propose an enhancement to the Fediverse (and maybe even web standards) to make Link Previews great: the Link Preview Manifest.
No video for this post, since I was boring myself as I recorded.
Introduction
Link previews are seemingly one of those web features that mostly work – until they they start to scale, and you need to figure out how the sausage is made.
The Firefox implementation shows why. There, generating a preview means retrieving a page’s HTML and parsing it, discarding most of what was downloaded. Firefox is just one client, though.
In federated systems, where a single link can fan out across thousands of timelines and clients, this behavior can accidentally lead to distributed denial-of-service (DDOS) attacks, as observed by publishers using Mastodon.
In a 2024 article, It’s FOSS asked people to not share their links on Mastodon, explaining that:
When you share a link on Mastodon, a link preview is generated for it, right?
With Mastodon being a federated platform (a part of the Fediverse), the request to generate a link preview is not generated by just one Mastodon instance. There are many instances connected to it who also initiate requests for the content almost immediately.
And, this “fediverse effect” increases the load on the website’s server in a big way.
Sure, some websites may not get overwhelmed with the requests, but Mastodon does generate numerous hits, increasing the load on the server. Especially, if the link reaches a profile with more followers (and a broader network of instances).
Things have not improved much since then.
Link Previews as generated by most user agents are expensive to create, since many of the pages being previewed are generated dynamically, increasing resource usage and page generation time.
There’s got to be a better way, and in this post, I am proposing one: Link Preview Manifest.
Please steal this idea if it is good!
Link Preview Manifest
A Link Preview Manifest is a small, cacheable resource that provides preview-specific metadata for a URL without requiring clients to fetch or parse the full HTML document.
Publishing software can generate this resource whenever the previewed document is created or updated once and it can be stored as a static file that does not need to be regenerated for each link preview request.
Discovery Mechanism
HTTP Headers
User agents can request a preview for a URI via a call to get the HEAD of a URI:
HEAD https://example.com/posts/hello-world/
User agents would receive some headers in response.
HTTP/1.1 200 OK
Link: <https://example.com/posts/hello-world/index.preview.json>; rel="link-preview"
Link-Preview: available
Cache-Control: max-age=86400
Upon receipt of the URI’s HTTP headers, user agents should inspect the headers for a Link relation advertising a preview resource. If a resource is advertised, the user agent can GET the preview resource, rather than the URI being previewed.
This separates discovery from retrieval and avoids the expense of page generation and transfer. This differs from the existing solutions, which require user agents to GET the entire page to parse link preview metadata.
The Link header is used since it already provides a standardized mechanism for advertising related resources.
Guessed Fallback
While the primary discovery mechanism for link previews is Link header metadata, user agents can also look for previews in the page URI + .preview.json
Link in HTML
If publishers can’t set headers, they can instead define link previews as external resources:
<link rel="link-preview" href="index.preview.json" type="application/link-preview+json">
This is a secondary fallback, in situations where the publisher is on shared hosting or cannot update web server behavior to support updating Link headers.
Preview File
The preview JSON file is a small, cacheable and verifiable representation of a web resource, intended for link previews in clients. Its purpose is to allow clients to render previews without needing to download the actual resource, and supports identity verification for safe caching and federation.
| Field | Type | Required | Description |
|---|---|---|---|
version |
integer | ✅ | Version of the link preview spec. |
title |
string | ✅ | Human-readable headline or title of the content. |
description |
string | ✅ | Short, plain-text summary of the resource. |
url |
string | ✅ | Canonical URL of the resource; clients use this as the primary link target. |
site |
object | ✅ | Information about the site hosting the content. Contains: • name (string, required) — site or provider name• url (string, optional) — link to site home |
type |
string | ✅ | Resource type (article, video, photo, link, rich) - helps clients render appropriately. |
published |
string (ISO 8601) | ❌ | Publication date of the resource. Useful for displaying timestamps. |
images |
array of objects | ❌ | Array of preview images. Each object may include: • url (string, required)• width (integer, optional)• height (integer, optional)• integrity (string, optional, SRI hash) |
video |
object | ❌ | Optional video preview. May include: • url (string, required)• width / height (integers)• duration (integer, seconds)• integrity (string, optional) |
cache |
object | ❌ | Caching hints for clients and CDNs. Example: {"max_age": 86400} (seconds). |
integrity |
string | ❌ | SRI hash of resource, allowing clients to verify authenticity. Applies to: • images (string, optional)• entire file (string, optional) |
Examples
Article With Preview Image
{
"version": 1,
"type": "article",
"title": "Why Link Previews Should Be Explicit",
"description": "An argument for a lightweight web standard that avoids HTML scraping and supports federation.",
"url": "https://example.com/blog/explicit-link-previews",
"site": {
"name": "Example Blog",
"url": "https://example.com"
},
"published": "2026-02-09T12:00:00Z",
"images": [
{
"url": "https://example.com/media/explicit-previews.jpg",
"width": 1200,
"height": 630,
"integrity": "sha256-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa="
}
],
"cache": {
"max_age": 86400
},
"integrity": "sha256-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb="
}
Image Gallery
{
"version": 1,
"type": "photo",
"title": "Weekend in Kyoto",
"description": "A short photo set from a weekend trip to Kyoto.",
"url": "https://example.com/photos/kyoto-weekend",
"site": {
"name": "Example Photos",
"url": "https://example.com"
},
"images": [
{
"url": "https://example.com/media/kyoto-1.jpg",
"width": 1080,
"height": 1080,
"integrity": "sha256-ccccccccccccccccccccccccccccccccccccccccccc="
},
{
"url": "https://example.com/media/kyoto-2.jpg",
"width": 1080,
"height": 1080,
"integrity": "sha256-ddddddddddddddddddddddddddddddddddddddddddd="
},
{
"url": "https://example.com/media/kyoto-3.jpg",
"width": 1080,
"height": 1080,
"integrity": "sha256-eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee="
}
],
"cache": {
"max_age": 43200
},
"integrity": "sha256-fffffffffffffffffffffffffffffffffffffffffff="
}
Video
{
"version": 1,
"type": "video",
"title": "Federation Without Scraping",
"description": "A short talk on making link previews cheaper and safer for the fediverse.",
"url": "https://example.com/videos/federation-without-scraping",
"site": {
"name": "Example Videos",
"url": "https://example.com"
},
"images": [
{
"url": "https://example.com/media/video-poster.jpg",
"width": 1280,
"height": 720,
"integrity": "sha256-1111111111111111111111111111111111111111111="
}
],
"video": {
"url": "https://example.com/media/federation-talk.mp4",
"width": 1280,
"height": 720,
"duration": 315,
"integrity": "sha256-2222222222222222222222222222222222222222222="
},
"cache": {
"max_age": 86400
},
"integrity": "sha256-3333333333333333333333333333333333333333333="
}
Storage
Preview files can be generated statically as separate .preview.json files per page. These files can be generated at build time, alongside HTML.
On disk, this would look like:
/article/index.html
/article/index.preview.json
Client Flow
Step 1: Header-based Discovery
When a client wants to get link preview metadata:
- Perform a
HEADrequest to the URL. - Look for a Link header with rel=”link-preview”.
Example:
Link: <https://example.com/article/index.preview.json>;
rel="link-preview";
type="application/link-preview+json"
If found, proceed to step 3.
Step 2: Fallback Discovery
If a link header is not present in HEAD, user agents can try (in order):
- Predictable adjacent file
- Example:
https://example.com/article/index.preview.json
- Example:
- HTML <link> element
- Example:
<link rel="link-preview" href="index.preview.json">
- Example:
Clients should stop once they successfully discover the manifest file.
Step 3: Fetch the Link Preview Manifest
Now that we know where the manifest is located, we can download it.
- Do a
GETon the discovered link preview manifest - Output:
- Content-Type: application/link-preview+json
- a small JSON file
Step 4: Verify Integrity
If present, clients can verify the Subresource Integrity hash. If fetching media resources, individual hashes can be verified.
If verification fails, clients may fall back to parsing the page.
Step 5: Cache
Clients should respect HTTP caching headers to minimize load on publishers.
Step 6: Parse and Render
At this point, the client has the Link Preview Manifest containing the information that would previously have been manually parsed from page HTML. As we now have a manifest that encapsulates this data in a verifiable way, we can avoid parsing of page data.
Conclusion
The way that web developers currently do link previews are inefficient and wasteful, and advantages big tech players like Facebook and X, since they are centralized and can easily absorb the costs associated with scraping pages.
The web deserves a better way: preview data that is explicit, lightweight, cacheable, and verifiable. By separating preview metadata from page content, clients can get and share metadata without forcing web servers into expensive page generation.
This proposal extends the web incrementally - advanced hosts can advertise Link Preview Manifests via page headers, while simpler setups can rely on predictible locations and fallbacks linked from HTML. Clients can adopt the standard incrementally without needing to throw away their existing functionality. The standard itself can be versioned to meet forthcoming needs.
It doesn’t make sense for publishers to not want their content posted on Mastodon because it causes their web servers to buckle under the strain. As more and more clients generate link previews, we can help scale the federated web by making link metadata cheap to advertise, transfer and consume.
Importantly, this approach does not require new infrastructure. It works with static site generators, shared hosting, CDNs, and existing HTTP semantics. Advanced hosts can benefit from cheap discovery via headers, while simpler setups can rely on predictable file locations and HTML fallbacks. Clients can adopt it incrementally and fall back to legacy scraping when necessary.
Subresource Integrity makes it possible to federate previews without centralized trust or authentication, allowing instances to cache and redistribute previews confidently. Combined with aggressive caching and small payloads, this shifts link previews from a repeated scraping problem into a solved distribution problem.
If link previews are going to remain a foundational part of the federated web, they should be treated as first-class resources. Making them explicit is a small change, but one that moves us toward a more resilient and scalable web.
If you liked this material, please consider supporting me. You can message me or follow this blog on Mastodon.