📋 Table of Contents
What Are Link Previews?
When you share a link on Slack, Discord, or Twitter, you see a rich preview with an image, title, and description. This is called a "link preview" or "link unfurling".
Link previews make your app feel more polished and help users understand what a link is about before clicking.
The Problem with OG Images
Most websites provide Open Graph (OG) images for link previews. However:
- Many sites don't have OG images - Especially smaller sites or web apps
- OG images can be outdated - The actual page might look different
- Inconsistent sizes - Some are too small, some are wrong aspect ratio
- Some sites block OG crawlers - You get no preview at all
The Solution: Screenshot API
Instead of relying on OG images, you can generate a real screenshot of the website. This guarantees:
- ✅ Every link has a preview (even without OG tags)
- ✅ Previews show the actual current state
- ✅ Consistent image dimensions
- ✅ Works for any URL
Implementation
Basic Link Preview Function
async function generateLinkPreview(url) {
const API_KEY = 'your-api-key';
const API_URL = 'https://snapapi.alterra-solutions.com/v1/screenshot';
// Generate screenshot URL
const screenshotUrl = `${API_URL}?url=${encodeURIComponent(url)}&api_key=${API_KEY}&width=1200&height=630&response=binary`;
// Fetch the screenshot
const response = await fetch(screenshotUrl);
if (!response.ok) {
throw new Error('Failed to generate preview');
}
return response;
}
💡 Pro Tip: We use 1200×630 dimensions - this is the optimal size for social media previews (Twitter, Facebook, LinkedIn).
Express.js API Endpoint
const express = require('express');
const app = express();
app.get('/api/preview', async (req, res) => {
const { url } = req.query;
if (!url) {
return res.status(400).json({ error: 'URL required' });
}
try {
const API_KEY = process.env.SNAPAPI_KEY;
const screenshotUrl = `https://snapapi.alterra-solutions.com/v1/screenshot?url=${encodeURIComponent(url)}&api_key=${API_KEY}&width=1200&height=630&response=binary`;
const response = await fetch(screenshotUrl);
const buffer = await response.arrayBuffer();
res.set('Content-Type', 'image/png');
res.set('Cache-Control', 'public, max-age=86400'); // Cache for 24h
res.send(Buffer.from(buffer));
} catch (error) {
res.status(500).json({ error: 'Failed to generate preview' });
}
});
app.listen(3000);
Usage in Your Frontend
<!-- In your HTML/React/Vue -->
<img
src="/api/preview?url=https://github.com"
alt="Link Preview"
width="600"
height="315"
/>
Caching Previews
Generating screenshots on every request is expensive. Here's how to implement caching:
Redis Cache Example
const redis = require('redis');
const client = redis.createClient();
async function getCachedPreview(url) {
// Check cache first
const cached = await client.get(`preview:${url}`);
if (cached) {
return Buffer.from(cached, 'base64');
}
// Generate new screenshot
const screenshot = await generateLinkPreview(url);
const buffer = await screenshot.arrayBuffer();
// Cache for 24 hours
await client.setEx(
`preview:${url}`,
86400,
Buffer.from(buffer).toString('base64')
);
return Buffer.from(buffer);
}
✅ With caching, you can serve thousands of link previews while only generating each unique URL once per day!
Start Building Link Previews
Get 100 free screenshots per month to build your link preview system.
Get Your API Key →