Tutorial

Screenshot and PDF Generation in SvelteKit with SnapAPI

April 2026 — 7 min read

SvelteKit is Svelte's official full-stack application framework, combining server-side rendering, static site generation, and API route handling in a single elegant package. Its server-only modules and form actions make building secure, server-side API endpoints straightforward. In this tutorial, you will add screenshot and PDF generation to a SvelteKit application using SnapAPI, implementing the capture logic in a SvelteKit server route, protecting it with server-side session validation, and returning binary responses efficiently to the client.

SvelteKit Server Routes for Screenshot Generation

SvelteKit server routes are defined as +server.ts files within the src/routes directory. A GET handler in src/routes/api/screenshot/+server.ts maps to the URL /api/screenshot. The handler receives a RequestEvent object providing access to the URL, request headers, cookies, and platform environment. Use the url.searchParams API to extract the target URL parameter. Your SnapAPI key lives in SvelteKit's private environment variables -- defined in your .env file with a SNAPAPI_KEY variable and accessed through the $env/static/private module, which SvelteKit guarantees never to include in the client bundle.

Validating the Target URL

Never pass user-supplied URLs directly to an external API without validation. In your SvelteKit server route, instantiate a URL object inside a try-catch block to validate that the target URL is well-formed. Check that the URL protocol is http or https and reject anything using file, data, or javascript schemes. Consider implementing an allowlist of permitted domains if your application should only screenshot a known set of URLs rather than arbitrary user-provided ones. Return a structured error response with a 400 status code if validation fails, giving the client enough information to correct its request.

Calling SnapAPI and Streaming the Response

After URL validation, call the SnapAPI screenshot endpoint using the native fetch API available in SvelteKit's Node.js server environment. Set the Authorization header to your SnapAPI key retrieved from the private environment module. Await the SnapAPI response and check its status code before proceeding. On success, return a new Response object constructed from the SnapAPI response body, setting the Content-Type header to match the SnapAPI response -- either image/png for screenshots or application/pdf for PDFs. SvelteKit correctly handles Response objects that wrap ReadableStreams, streaming the binary content to the client without buffering the entire payload in server memory.

Form Actions for Screenshot Triggering

SvelteKit form actions handle POST requests from standard HTML forms without client-side JavaScript. This makes them ideal for screenshot generation triggered by user actions in a progressively enhanced SvelteKit application. Define a default action in a page's +page.server.ts file that reads the target URL from the form data, validates it, calls SnapAPI, uploads the result to cloud storage, and redirects to a success page with the stored screenshot URL. The entire workflow functions correctly even with JavaScript disabled in the browser, providing reliable screenshot generation across all client environments.

Caching Screenshots with SvelteKit Hooks

SvelteKit hooks intercept all incoming requests before they reach route handlers, making them an ideal location for request-level caching logic. In src/hooks.server.ts, check if the incoming request is for your screenshot route and whether a cached screenshot exists for the requested URL hash in Redis or another server-side cache. If a cached result exists, return it immediately without executing the route handler. Cache misses fall through to the route handler normally, which calls SnapAPI and writes the result to the cache before returning. This caching layer operates transparently from the perspective of both the route handler and the client.

Deploying SvelteKit with Screenshot Routes

SvelteKit adapts to different deployment targets through its adapter system. The Node.js adapter deploys your screenshot service as a traditional Node.js server. The Vercel adapter deploys API routes as serverless functions. The Cloudflare adapter deploys to Cloudflare Workers. In all cases, your SnapAPI key is stored as a private environment variable in the deployment platform and accessed through the $env/static/private module without any code changes between deployment targets. Choose the adapter that matches your infrastructure, run the SvelteKit build, and deploy -- your screenshot route is live globally within minutes.

Production Patterns for SvelteKit Screenshot Services

A basic SvelteKit screenshot route handles the core request-response cycle cleanly. Moving to production requires additional patterns around error handling, observability, multi-format output, and the security considerations specific to screenshot services exposed to external users. This section covers the production-hardening steps that separate a functioning prototype from a reliable service.

Graceful Error Handling in SvelteKit Routes

SvelteKit's error helper function from @sveltejs/kit throws an HTTP error that SvelteKit catches and renders through your error page. In a screenshot API route, however, you want structured JSON error responses rather than HTML error pages. Instead of using the error helper, return Response objects directly with appropriate status codes and JSON bodies. Define a consistent error response schema -- status code, error code string, human-readable message -- and use it across all error paths in your screenshot route: invalid URL (400), unauthorized (401), SnapAPI timeout (504), and unexpected failure (500). Clients can parse this consistent structure to display appropriate error messages and implement retry logic for transient failures.

Environment-Specific Configuration

SvelteKit's private environment module resolves variables from your .env file during development and from the deployment platform's environment variable system in production. For screenshot services, define separate SnapAPI keys for development and production environments to prevent development testing from consuming production API credits. Add a SNAPAPI_BASE_URL variable alongside SNAPAPI_KEY to make it easy to point development environments at a mock server for testing without making real SnapAPI calls. SvelteKit's build-time environment variable resolution ensures these values are embedded securely without appearing in client bundles.

Logging and Tracing

Server-side logging in SvelteKit runs in Node.js, giving you access to the full Node.js logging ecosystem. Use a structured logging library to emit JSON log entries from your screenshot route that include the target URL (sanitized of sensitive parameters), the SnapAPI response time, the HTTP status returned to the client, and a correlation ID extracted from the incoming request headers. Configure your logging library to write to stdout in production, where your deployment platform's log aggregation picks it up automatically. Add the correlation ID to your SnapAPI request headers so that SnapAPI support can trace a specific request if needed. This structured logging setup makes debugging production screenshot failures fast and consistent.

Rate Limiting with SvelteKit Hooks

SvelteKit's server hooks run before route handlers and are the correct place for cross-cutting concerns like rate limiting. Implement a sliding window rate limiter in your hooks.server.ts that tracks request counts per IP address or authenticated user ID in Redis. If the rate limit is exceeded, return a 429 response from the hook before the request reaches your screenshot route handler, preventing any SnapAPI calls from being made for over-quota requesters. Store the rate limit counter with an expiry matching your window size so that Redis automatically cleans up counters from inactive clients. Document your rate limits clearly in your API documentation so that legitimate clients can implement appropriate backoff and retry logic.

Open Graph Image Generation with SvelteKit and SnapAPI

Generating custom Open Graph images for each page of your SvelteKit application significantly improves engagement when content is shared on LinkedIn, Twitter, and Slack. The standard approach involves a SvelteKit server route that accepts page metadata as query parameters, renders an HTML template populated with that metadata, passes the template URL to SnapAPI with a 1200x630 viewport, and returns the resulting PNG with a long-lived cache header. In practice, you create a dedicated SvelteKit route at /og/[slug] that renders a minimal Svelte component styled for OG image dimensions. Your main page routes reference this OG image URL in their Open Graph meta tags, which SvelteKit's head function populates server-side. Social platforms request the OG image URL when a link is shared, your server route captures it via SnapAPI, caches it aggressively, and returns the PNG. The result is a unique, on-brand social sharing image for every page of your SvelteKit application, generated automatically from your existing page data without any manual design work.

Start integrating SnapAPI into your SvelteKit application today with the free tier at snapapi.pics. Create an account, retrieve your API key, and implement your first server route screenshot endpoint in under 30 minutes following the patterns in this guide.