April 2026 · 6 min read · Blog
Screenshot API for Svelte & SvelteKit — Server Endpoints, Stores, and OG Images
Integrate SnapAPI into Svelte and SvelteKit apps: server-only API routes, Svelte stores for state management, and automated OG image generation for your content.
Why Svelte Apps Benefit from a Screenshot API
Svelte and SvelteKit power a growing share of content sites, documentation platforms, portfolio sites, and SaaS dashboards. All of these share a common set of screenshot needs: OG image generation for social sharing, PDF export for reports and invoices, and visual regression testing in CI. SnapAPI is a plain REST endpoint — no framework-specific SDK, just fetch — which means it works identically in Svelte components, SvelteKit server hooks, and standalone Node.js scripts.
SvelteKit Server Route for Screenshot Proxy
In SvelteKit, always proxy SnapAPI calls through a server route to keep your API key out of the browser bundle. Create the route at src/routes/api/screenshot/+server.ts:
// src/routes/api/screenshot/+server.ts
import { env } from '$env/dynamic/private';
import { error } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async ({ url }) => {
const target = url.searchParams.get('url');
if (!target) throw error(400, 'url is required');
const params = new URLSearchParams({
url: target,
format: url.searchParams.get('format') || 'webp',
width: url.searchParams.get('width') || '1280',
access_key: env.SNAP_KEY
});
const resp = await fetch(`https://api.snapapi.pics/v1/screenshot?${params}`);
if (!resp.ok) throw error(resp.status, 'SnapAPI error');
return new Response(resp.body, {
headers: {
'Content-Type': resp.headers.get('content-type') || 'image/webp',
'Cache-Control': 'public, max-age=3600'
}
});
};
Your Svelte components call /api/screenshot?url=... — the API key never leaves your server. SvelteKit's streaming response support means the screenshot binary is piped directly to the client without buffering the entire image in memory.
Svelte Store for Screenshot State
For Svelte components that capture screenshots on demand, a writable store manages loading and result state cleanly:
// lib/stores/screenshot.ts
import { writable } from 'svelte/store';
interface ScreenshotState {
loading: boolean;
url: string | null;
error: string | null;
}
export function createScreenshotStore() {
const { subscribe, set, update } = writable<ScreenshotState>({
loading: false, url: null, error: null
});
async function capture(targetUrl: string, options: Record<string, string> = {}) {
update(s => ({ ...s, loading: true, error: null }));
try {
const params = new URLSearchParams({ url: targetUrl, ...options });
const resp = await fetch('/api/screenshot?' + params);
if (!resp.ok) throw new Error('Screenshot failed: ' + resp.status);
const blob = await resp.blob();
const objectUrl = URL.createObjectURL(blob);
set({ loading: false, url: objectUrl, error: null });
} catch (e) {
update(s => ({ ...s, loading: false, error: e instanceof Error ? e.message : 'Error' }));
}
}
return { subscribe, capture };
}
Use it in any Svelte component:
<script lang="ts">
import { createScreenshotStore } from '$lib/stores/screenshot';
const screenshot = createScreenshotStore();
</script>
<button on:click={() => screenshot.capture('https://example.com')} disabled={$screenshot.loading}>
{$screenshot.loading ? 'Capturing...' : 'Take Screenshot'}
</button>
{#if $screenshot.url}
<img src={$screenshot.url} alt="Screenshot" />
{/if}
{#if $screenshot.error}
<p class="error">{$screenshot.error}</p>
{/if}
OG Image Generation for SvelteKit Content
SvelteKit content sites need OG images for every post or page. Hook into your build process or a post-publish webhook to generate screenshots automatically. A build-time script reads your content directory, screenshots each page, and saves the WebP images as static assets:
// scripts/generate-og.ts
import { readdir, writeFile } from 'fs/promises';
const BASE_URL = 'https://your-sveltekit-site.com';
const SNAP_KEY = process.env.SNAP_KEY!;
const OUTPUT_DIR = 'static/og';
const pages = await readdir('src/content/blog');
for (const file of pages.filter(f => f.endsWith('.md'))) {
const slug = file.replace('.md', '');
const url = `${BASE_URL}/blog/${slug}`;
const resp = await fetch(
`https://api.snapapi.pics/v1/screenshot?` +
new URLSearchParams({ url, format: 'webp', width: '1200', height: '630', access_key: SNAP_KEY })
);
await writeFile(`${OUTPUT_DIR}/${slug}.webp`, Buffer.from(await resp.arrayBuffer()));
console.log('OG image generated:', slug);
}
SvelteKit Hooks for Automatic Screenshot on Publish
If your SvelteKit app has a CMS or admin area where content is published, use SvelteKit hooks to trigger screenshot generation as a side effect of publish actions. The hook runs server-side, calls SnapAPI asynchronously (without blocking the response), and stores the screenshot URL in your database for later use as the og:image meta tag value.
Getting Started
Sign up at snapapi.pics, get your free API key (200 screenshots/month, no credit card), and add it to your .env file as SNAP_KEY. In SvelteKit, access it via $env/dynamic/private to ensure it is never exposed to the browser. Your first screenshot route is live in minutes — no npm packages, no configuration beyond the environment variable.