Screenshot API for SvelteKit

Generate screenshots, OG images, and PDFs from your SvelteKit app without Puppeteer. Works with SvelteKit server routes and Vercel/Cloudflare Workers deployments.

Start Free — 200 Screenshots/mo

Why SvelteKit Developers Need a Screenshot API

SvelteKit is increasingly deployed to edge runtimes — Cloudflare Workers, Vercel Edge Functions, and similar environments where Node.js APIs are limited or absent. Running Puppeteer or Playwright in these environments is not possible: there is no Chromium binary, no subprocess spawning, and often strict memory limits. Even on traditional Node.js deployments via adapter-node, adding Chromium increases container sizes dramatically and adds operational complexity that conflicts with SvelteKit's lean build philosophy.

SnapAPI solves this with a single fetch call from any SvelteKit server route or API endpoint. Your SvelteKit app stays lean, deploys to any adapter, and screenshot generation just works — whether you're on Vercel, Cloudflare Workers, Netlify, or a self-hosted VPS.

SvelteKit API Route: Screenshot Endpoint

// src/routes/api/screenshot/+server.ts
import type { RequestHandler } from './$types';
import { SNAPAPI_KEY } from '$env/static/private';
import { json, error } from '@sveltejs/kit';

export const POST: RequestHandler = async ({ request }) => {
  const { url, fullPage = false, width = 1280 } = await request.json();
  if (!url) throw error(400, 'url is required');

  const params = new URLSearchParams({
    access_key: SNAPAPI_KEY,
    url,
    full_page: String(fullPage),
    width: String(width),
  });
  const res = await fetch(`https://snapapi.pics/v1/screenshot?${params}`);
  const data = await res.json();
  return json({ screenshot_url: data.url });
};

OG Image Generation in SvelteKit

Create a server route that generates OG images for each page. The pattern is the same as Next.js: a template page receives dynamic content via query params, SnapAPI captures it, and the result is cached and returned from the og:image meta tag.

// src/routes/api/og/[slug]/+server.ts
import { SNAPAPI_KEY, PUBLIC_URL } from '$env/static/private';
import { redirect } from '@sveltejs/kit';

export const GET = async ({ params }) => {
  const ogTemplate = `${PUBLIC_URL}/og-template/${params.slug}`;
  const snapParams = new URLSearchParams({
    access_key: SNAPAPI_KEY,
    url: ogTemplate,
    width: '1200',
    height: '630',
    format: 'png',
  });
  const res = await fetch(`https://snapapi.pics/v1/screenshot?${snapParams}`);
  const { url } = await res.json();
  throw redirect(302, url);
};

SvelteKit + Cloudflare Workers

When deploying SvelteKit to Cloudflare Workers with adapter-cloudflare, you get access to the Web Platform APIs including fetch. SnapAPI works perfectly in this environment since it only requires fetch. Add SNAPAPI_KEY to your Cloudflare Worker environment variables and the integration works identically to any other environment.

// wrangler.toml - add your API key
[vars]
# Set SNAPAPI_KEY as a secret: wrangler secret put SNAPAPI_KEY

// Works in Cloudflare Workers because it is just a fetch call
const res = await fetch(
  `https://snapapi.pics/v1/screenshot?access_key=${env.SNAPAPI_KEY}&url=${encodeURIComponent(url)}`
);
const { url: screenshotUrl } = await res.json();

PDF Export from SvelteKit Pages

Generate PDFs from any SvelteKit page or component. Create a dedicated rendering route for the content you want to export as PDF, capture it with SnapAPI, and stream the result to the user. This works for invoices, reports, data exports, and any content that benefits from pixel-perfect browser rendering.

// src/routes/api/export-pdf/+server.ts
export const GET = async ({ url, locals }) => {
  const reportId = url.searchParams.get('id');
  const token = locals.session?.token;
  const targetUrl = `${PUBLIC_URL}/reports/${reportId}/render?token=${token}`;

  const params = new URLSearchParams({
    access_key: SNAPAPI_KEY,
    url: targetUrl,
    format: 'pdf',
    full_page: 'true',
  });
  const res = await fetch(`https://snapapi.pics/v1/screenshot?${params}`);
  const { url: pdfUrl } = await res.json();
  return new Response(null, { status: 302, headers: { Location: pdfUrl } });
};

Environment Variables and Security

Store your SNAPAPI_KEY in .env for local development and in your deployment platform's environment variable settings for production. SvelteKit's $env/static/private module ensures the key is never exposed to client-side code. Never import from $env/static/public for API keys — the private module is type-checked and only accessible in server-side code.

Pricing

Free tier: 200 screenshots/month, no credit card. Starter: $19/mo (5,000). Growth: $79/mo (50,000). Works on any SvelteKit adapter — node, cloudflare, vercel, netlify, or static. Get your free API key.

Start Free — No Credit Card

SvelteKit Loading Functions and Screenshot Pre-generation

SvelteKit's server load functions run on the server before the page renders, making them ideal for pre-fetching or pre-generating screenshot URLs. For pages where you know a screenshot will be needed, generate it in the load function and pass the URL to the page component as part of the page data. This ensures the screenshot is ready before the user requests it rather than generating on demand.

// src/routes/reports/[id]/+page.server.ts
import type { PageServerLoad } from './$types';
import { SNAPAPI_KEY } from '$env/static/private';

export const load: PageServerLoad = async ({ params, locals }) => {
  const report = await db.reports.findById(params.id);

  // Check if screenshot already generated
  if (!report.screenshotUrl) {
    const signedUrl = generateSignedUrl(`/reports/${params.id}/render`);
    const snap = await fetch(
      `https://snapapi.pics/v1/screenshot?access_key=${SNAPAPI_KEY}&url=${encodeURIComponent(signedUrl)}&full_page=true`
    );
    const { url } = await snap.json();
    await db.reports.update(params.id, { screenshotUrl: url });
    report.screenshotUrl = url;
  }

  return { report };
};

Handling Screenshots in SvelteKit Actions

SvelteKit form actions can trigger screenshot generation as part of form submissions. When a user submits a "generate report" form, the action generates the report data, then fires a screenshot job. This keeps screenshot generation server-side and out of client code entirely.

// src/routes/reports/+page.server.ts
export const actions = {
  generate: async ({ request, locals }) => {
    const data = await request.formData();
    const reportId = await createReport(data);

    // Fire screenshot in background (non-blocking)
    generateScreenshotAsync(reportId);  // your background job

    return { success: true, reportId };
  }
} satisfies Actions;

SvelteKit Universal Screenshot Utility

Create a shared utility module that all your SvelteKit server routes can import for consistent screenshot generation, error handling, and caching.

// src/lib/server/screenshots.ts
import { SNAPAPI_KEY } from '$env/static/private';

interface ScreenshotOptions {
  url: string;
  width?: number;
  height?: number;
  fullPage?: boolean;
  format?: 'png' | 'jpeg' | 'webp' | 'pdf';
}

export async function capture(opts: ScreenshotOptions): Promise {
  const params = new URLSearchParams({
    access_key: SNAPAPI_KEY,
    url: opts.url,
    width: String(opts.width ?? 1280),
    full_page: String(opts.fullPage ?? false),
    format: opts.format ?? 'png',
  });
  if (opts.height) params.set('height', String(opts.height));

  const res = await fetch(`https://snapapi.pics/v1/screenshot?${params}`);
  if (!res.ok) throw new Error(`SnapAPI error: ${res.status}`);
  const data = await res.json();
  return data.url;
}

export const captureOG = (url: string) =>
  capture({ url, width: 1200, height: 630, format: 'png' });

export const capturePDF = (url: string) =>
  capture({ url, fullPage: true, format: 'pdf' });

Testing Your SvelteKit Screenshot Integration

Mock the SnapAPI endpoint in your SvelteKit tests using vitest and MSW (Mock Service Worker). This lets you test screenshot generation logic without making real API calls during test runs, keeping tests fast and deterministic.

SvelteKit developers who have integrated SnapAPI report the fastest time-to-value for OG image generation. The pattern — a server route that calls SnapAPI and returns a CDN URL — is idiomatic SvelteKit and requires no special packages or configuration beyond adding the API key to your environment. The entire integration, including caching, typically takes 2–3 hours to implement and deploy. Create your free SnapAPI account and have OG images generating from your SvelteKit app today.

SvelteKit Screenshots: Common Questions

Does SnapAPI work with SvelteKit's SSR? Yes. The API call happens in server-side code inside server routes or load functions. The result is a CDN URL — a plain string that passes seamlessly from server to client as part of page data or API responses. There is nothing SvelteKit-specific about the integration beyond using $env/static/private for your API key.

What about SvelteKit's streaming SSR? SnapAPI calls are async and return quickly (typically one to three seconds). They fit naturally into async load functions without blocking the streaming response. For very long-running captures, use a background job pattern — fire the screenshot asynchronously and update the database when complete, then poll from the frontend until the URL is available.

Can I use SnapAPI in a SvelteKit library package? Yes. Include SnapAPI as an optional peer dependency and document the SNAPAPI_KEY environment variable requirement. Your library users configure the key in their own environment; the library makes the fetch call using it. This pattern works cleanly with SvelteKit's server-only environment variable system.

Does the pricing page at /pricing work the same as the API? The /pricing page at snapapi.pics/pricing is informational. All API access goes through api keys issued from the dashboard. Your SvelteKit app accesses the API with its server-side key — users never see or interact with your API key. Ready to start? Create your free account.

SnapAPI is the only screenshot API with official SDKs for all six major languages including Swift and Kotlin for mobile developers. Whether your SvelteKit backend needs screenshots for web, or your team also builds mobile apps alongside the web product, one API key covers every platform. The free tier is permanent and never expires. Two hundred calls per month, every month, at no cost. No trial period, no credit card, no expiration. Upgrade only when your volume requires it. Get started now.