Screenshot API for Next.js

Generate screenshots, PDFs, and scrape structured data from Next.js applications. Works in App Router, Pages Router, API routes, and Edge Functions.

Start Free — 200 captures/month
App RouterEdge ReadyTypeScript SDKOG Image Gen

Quick Start: Next.js API Route

Create an API route that proxies screenshot requests to SnapAPI. This keeps your API key server-side and lets you add auth, caching, and rate limiting in one place.

// app/api/screenshot/route.ts
import { NextRequest, NextResponse } from "next/server";

export async function POST(req: NextRequest) {
  const { url, format = "png", fullPage = true } = await req.json();

  if (!url) return NextResponse.json({ error: "url required" }, { status: 400 });

  const res = await fetch("https://api.snapapi.pics/v1/screenshot", {
    method: "POST",
    headers: {
      "X-Api-Key": process.env.SNAPAPI_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ url, format, full_page: fullPage }),
  });

  const data = await res.json();
  return NextResponse.json(data);
}

OG Image Generation with Next.js

Next.js 13+ has built-in OG image generation via @vercel/og, but SnapAPI gives you more flexibility — render any URL or HTML to an image, not just React JSX. This is useful when you need to capture an existing page exactly as it renders in a browser, including all its stylesheets, fonts, and dynamic content.

// app/api/og/route.ts
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const title = searchParams.get("title") ?? "My Site";
  const slug = searchParams.get("slug") ?? "";

  // Build the public URL of the article page
  const articleUrl = `${process.env.NEXT_PUBLIC_SITE_URL}/blog/${slug}`;

  const snap = await fetch("https://api.snapapi.pics/v1/screenshot", {
    method: "POST",
    headers: { "X-Api-Key": process.env.SNAPAPI_KEY! },
    body: JSON.stringify({
      url: articleUrl,
      format: "png",
      width: 1200,
      height: 630,
      full_page: false,
      wait_for: ".article-content",
    }),
    next: { revalidate: 3600 }, // cache for 1 hour via Next.js fetch cache
  });

  const { url: imageUrl } = await snap.json();
  return Response.redirect(imageUrl);
}

Next.js Edge Functions

SnapAPI works perfectly in Next.js Edge Runtime since it is a pure HTTP API with no Node.js-specific dependencies. Edge functions can call SnapAPI and stream or redirect the result to the user with minimal latency overhead. Mark your route as edge with export const runtime = "edge" and the SnapAPI fetch call works identically.

TypeScript SDK Integration

// lib/snapapi.ts
import { SnapAPI } from "snapapi-js";

export const snapapi = new SnapAPI({
  apiKey: process.env.SNAPAPI_KEY!,
});

// Usage in a Server Component or API route
const result = await snapapi.screenshot({
  url: "https://example.com",
  format: "png",
  fullPage: true,
  width: 1440,
});

console.log(result.url); // CDN URL to the screenshot

Next.js Caching Strategy

Next.js extended fetch caching works with SnapAPI calls. Use next: { revalidate: N } on the fetch call to cache the screenshot URL at the Next.js layer, reducing API calls for frequently requested screenshots. For dynamic content that changes per request, use cache: "no-store" to always get a fresh capture. The CDN-hosted image URL returned by SnapAPI is also independently cacheable via standard HTTP cache headers.

Vercel Deployment

Add SNAPAPI_KEY to your Vercel environment variables and SnapAPI works identically in development, preview, and production deployments. No special configuration, no binary dependencies, no Docker layer changes. The same API call that works locally works on Vercel Functions and Edge Functions without modification. For teams using Vercel for their Next.js deployments, SnapAPI is the cleanest way to add screenshot and PDF capabilities without adding infrastructure complexity.

Pricing

Free: 200 captures/month. Starter: $19/month, 5K captures. Pro: $79/month, 50K captures. Business: $299/month, 500K captures. All plans include screenshot, PDF, scrape, and AI extraction.

Add Screenshots to Your Next.js App →

Next.js App Router Integration

The Next.js App Router introduced React Server Components and a completely new data-fetching model. SnapAPI fits naturally into this architecture — call it from a Server Component or a Route Handler without any client-side bundle cost. Authentication happens server-side, your API key never reaches the browser.

Route Handler (app/api/screenshot/route.ts)

import { NextRequest, NextResponse } from 'next/server';

export const runtime = 'nodejs'; // use 'edge' for sub-50ms cold starts

export async function POST(req: NextRequest) {
  const { url } = await req.json();

  const res = await fetch('https://api.snapapi.pics/v1/screenshot', {
    method: 'POST',
    headers: {
      'X-Api-Key': process.env.SNAPAPI_KEY!,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      url,
      format: 'png',
      fullPage: false,
      width: 1280,
      height: 800,
      blockAds: true,
    }),
  });

  const data = await res.json();
  return NextResponse.json({ screenshot: data.url });
}

OG Image Generation with SnapAPI

Open Graph images are critical for social sharing. Instead of shipping a heavy canvas renderer to the edge, use SnapAPI to capture a pre-built HTML template and cache the result in your CDN. The workflow is: render your OG template at a known URL → call SnapAPI → store the PNG in object storage → return the CDN URL. Cloudflare R2 or Vercel Blob both work perfectly.

// app/api/og/route.ts
export async function GET(req: NextRequest) {
  const slug = req.nextUrl.searchParams.get('slug') ?? 'home';
  const templateUrl = `https://yourapp.com/og-template?slug=${slug}`;

  const snap = await fetch('https://api.snapapi.pics/v1/screenshot', {
    method: 'POST',
    headers: { 'X-Api-Key': process.env.SNAPAPI_KEY! },
    body: JSON.stringify({ url: templateUrl, width: 1200, height: 630 }),
  }).then(r => r.json());

  // Redirect to the hosted image
  return NextResponse.redirect(snap.url);
}

Server-Side Rendering with TypeScript Types

Use the snapapi-js SDK for fully typed requests. Install with npm i snapapi-js, then call from any async Server Component. The SDK automatically handles retries, response parsing, and normalises storage URLs across formats.

// app/preview/page.tsx  (Server Component)
import SnapAPI from 'snapapi-js';

const snap = new SnapAPI(process.env.SNAPAPI_KEY!);

export default async function PreviewPage({
  searchParams,
}: {
  searchParams: { url?: string };
}) {
  if (!searchParams.url) return <p>No URL provided</p>;

  const result = await snap.screenshot({
    url: searchParams.url,
    device: 'iPhone 15 Pro',
    fullPage: true,
  });

  return (
    <main>
      <img src={result.url} alt="Screenshot" style={{ width: '100%' }} />
    </main>
  );
}

Edge Functions & Middleware

SnapAPI calls originate from your server, so they work fine in both Node.js and Edge runtimes. In Edge Functions, set export const runtime = 'edge' and use the native fetch API directly — no Node.js-specific APIs required. This gives you sub-10ms cold starts on Vercel's edge network while still calling SnapAPI from a secure, server-side context.

For high-volume pipelines, consider offloading screenshot jobs to a background queue (like BullMQ or Inngest) instead of blocking the HTTP request. Return a job ID immediately and poll for completion — this keeps your API latency low even when SnapAPI takes 3-5 seconds for complex pages.

Device Emulation in Next.js

SnapAPI includes 30+ device presets — pass any preset name as the device parameter. This is ideal for responsive design QA pipelines: generate screenshots across iPhone 15 Pro, iPad Pro, and desktop in a single batch, then diff them against your baseline images to catch regressions automatically.

Environment Variables & Deployment

Store your key as SNAPAPI_KEY in .env.local for development and in Vercel's environment variables dashboard for production. Never prefix API keys with NEXT_PUBLIC_ — that would expose them to the client bundle. All SnapAPI calls should stay server-side.

SnapAPI's Free plan gives you 200 captures per month at no cost — enough to prototype and test your Next.js integration before committing to a paid plan. Upgrade to Starter ($19/mo, 5K requests) when you're ready to ship to production.

Frequently Asked Questions

Can I use SnapAPI with Next.js Middleware?

Yes, but indirectly. Middleware runs on the Edge Runtime which doesn't support all Node.js APIs, but since SnapAPI calls are standard fetch requests, you can call them from Middleware. That said, Middleware runs on every request and adding a 2-4 second API call there would devastate your latency. Use Middleware for auth checks and redirects only — move SnapAPI calls to Route Handlers or Server Components.

How do I handle timeouts in Next.js Route Handlers?

Vercel's Hobby plan has a 10-second execution limit on serverless functions. For screenshot workloads that can take 3-8 seconds, use the Pro plan (60s limit) or offload to a background job. The pattern: enqueue the job via Route Handler, return a job ID, let the client poll a status endpoint. This keeps your Route Handler fast and lets the screenshot work happen asynchronously.

Is there a Next.js example project on GitHub?

Check our SDK repository at github.com/Sleywill/snapapi-js for the JavaScript SDK with TypeScript types. The README includes a full Next.js App Router example. For the MCP Server integration (works with Claude Code and Cursor), see github.com/Sleywill/snapapi-mcp.

How does SnapAPI compare to self-hosting Playwright in Next.js?

Self-hosting Playwright means bundling Chromium into your deployment — which adds ~300MB to your Docker image and makes serverless deployments (Vercel, Netlify) impractical since they have 50MB function size limits. SnapAPI keeps Chromium off your servers entirely. You make an HTTP call, we run the browser, you get back a URL. Your deployment stays lean and your Vercel bill stays predictable.

What about @vercel/og for Open Graph images?

@vercel/og uses Satori (an SVG renderer) which supports a subset of CSS. It's excellent for simple text-and-image OG cards but breaks on complex layouts, CSS Grid, animations, or custom web fonts loaded from CSS. SnapAPI uses a real Chromium browser, so any page that renders in Chrome will render in your screenshot — no CSS limitations, no layout workarounds.

Start Free — 200 Screenshots/Month

No credit card required. Get your API key in 30 seconds and ship your first Next.js screenshot feature today.

Get Free API Key