Screenshot API for TypeScript: Node.js, Edge & Serverless

Use SnapAPI to capture screenshots from TypeScript. Works with Node.js, Deno, Bun, Cloudflare Workers, and Next.js. Typed SDK or plain fetch — zero browser dependencies.

Start Free — 200 captures/mo View Docs

Screenshot API for TypeScript Projects

SnapAPI integrates with TypeScript projects on Node.js, Deno, Bun, and edge runtimes without any SDK required. The API accepts standard HTTP requests and returns image bytes, JSON, or PDF depending on the endpoint. Full TypeScript type definitions are available in the official snapapi-js package, giving you autocomplete and type safety for all request parameters and response shapes.

Typed API Client with snapapi-js

npm install snapapi-js

// screenshot.ts
import SnapAPI from "snapapi-js";

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

const result = await client.screenshot({
  url: "https://example.com",
  fullPage: true,
  format: "png",
  blockAds: true,
});

// result.image is a Buffer
await fs.writeFile("output.png", result.image);
console.log(`Captured: ${result.image.length} bytes`);

The snapapi-js SDK provides full TypeScript types for all 9 endpoints: screenshot, scrape, extract, analyze, pdf, video, get_usage, list_devices, and ping. Each method returns a typed response object so TypeScript catches mismatched parameter types at compile time rather than at runtime.

Using fetch Directly

// Works in Node 18+, Deno, Bun, and Cloudflare Workers
const params = new URLSearchParams({
  url: "https://example.com",
  full_page: "true",
  format: "jpeg",
  quality: "85",
});

const res = await fetch(
  `https://api.snapapi.pics/v1/screenshot?${params}`,
  { headers: { "X-Api-Key": process.env.SNAPAPI_KEY! } }
);

if (!res.ok) throw new Error(`SnapAPI error: ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
await fs.writeFile("screenshot.jpg", buffer);

The native fetch approach works across all modern TypeScript runtimes and requires zero dependencies. Use it when you want to minimize bundle size in edge functions or keep your dependency tree clean in serverless deployments.

TypeScript on Edge and Serverless

Cloudflare Workers, Vercel Edge Functions, and Deno Deploy all support the Fetch API natively, making SnapAPI calls trivial from edge environments. Since SnapAPI handles the browser rendering on its own infrastructure, your edge function stays lightweight — there is no Chromium binary to bundle, no memory overhead, and no cold-start penalty from a large dependency.

For Next.js projects, call SnapAPI from API routes or server actions rather than client components. This keeps your API key server-side and allows you to cache responses in the Next.js data cache with fetch revalidation:

// app/api/preview/route.ts
export async function GET(req: Request) {
  const url = new URL(req.url).searchParams.get("url");
  const res = await fetch(
    `https://api.snapapi.pics/v1/screenshot?url=${encodeURIComponent(url!)}&format=jpeg`,
    {
      headers: { "X-Api-Key": process.env.SNAPAPI_KEY! },
      next: { revalidate: 3600 }, // cache for 1 hour
    }
  );
  const image = await res.arrayBuffer();
  return new Response(image, { headers: { "Content-Type": "image/jpeg" } });
}

This pattern creates a URL preview endpoint that caches screenshots for an hour using Next.js built-in data caching. It is ideal for link-preview cards in a social feed or thumbnail generation for a CMS where content does not change frequently.

Concurrent Batch Captures in TypeScript

TypeScript's async/await and Promise.all make concurrent screenshot batches trivial to implement without blocking the event loop. The following pattern captures multiple URLs in parallel and writes the results to disk as they complete:

import { writeFile } from "fs/promises";

async function capture(url: string, apiKey: string): Promise<Buffer> {
  const params = new URLSearchParams({ url, full_page: "true", format: "jpeg" });
  const res = await fetch(`https://api.snapapi.pics/v1/screenshot?${params}`, {
    headers: { "X-Api-Key": apiKey },
  });
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  return Buffer.from(await res.arrayBuffer());
}

const urls = [
  "https://example.com/page-1",
  "https://example.com/page-2",
  "https://example.com/page-3",
];

const results = await Promise.all(
  urls.map((url, i) =>
    capture(url, process.env.SNAPAPI_KEY!).then(buf =>
      writeFile(`screenshot-${i}.jpg`, buf)
    )
  )
);
console.log(`Captured ${results.length} screenshots`);

For large batches, limit concurrency with a semaphore or a library like p-limit to avoid overwhelming your event loop and exceeding rate limits. p-limit(10) allows at most 10 simultaneous in-flight requests, regardless of how many URLs are in your input array.

TypeScript with Express

For an Express API that generates on-demand screenshots, wrap the SnapAPI call in a route handler and stream the response directly to the client. This avoids buffering the entire image in memory when the image is large:

app.get("/preview", async (req, res) => {
  const { url } = req.query as { url: string };
  const params = new URLSearchParams({ url, format: "jpeg", quality: "85" });
  const upstream = await fetch(
    `https://api.snapapi.pics/v1/screenshot?${params}`,
    { headers: { "X-Api-Key": process.env.SNAPAPI_KEY! } }
  );
  res.setHeader("Content-Type", "image/jpeg");
  res.setHeader("Cache-Control", "public, max-age=3600");
  // @ts-ignore — ReadableStream pipe
  upstream.body!.pipeTo(new WritableStream({
    write(chunk) { res.write(chunk); },
    close() { res.end(); },
  }));
});

The streaming pattern is useful when serving screenshot proxies to browsers because it reduces time-to-first-byte — the browser starts receiving image data as soon as SnapAPI begins returning it. Add a Redis cache layer in front of the route to avoid redundant API calls for frequently requested URLs.

All SnapAPI Features from TypeScript

Every SnapAPI endpoint is available from TypeScript with identical syntax. Switch the path to access different capabilities without changing your HTTP client code.

const BASE = "https://api.snapapi.pics";
const KEY = process.env.SNAPAPI_KEY!;
const h = { "X-Api-Key": KEY };

// Scrape rendered HTML
const scrape = await fetch(`${BASE}/v1/scrape?url=https://example.com`, { headers: h });
const { html } = await scrape.json();

// Extract structured data with CSS selectors
const extract = await fetch(`${BASE}/v1/extract`, {
  method: "POST",
  headers: { ...h, "Content-Type": "application/json" },
  body: JSON.stringify({
    url: "https://shop.example.com/product/1",
    selectors: { title: "h1", price: ".price", stock: "[data-stock]" }
  })
});
const { data } = await extract.json();

// Generate PDF
const pdf = await fetch(`${BASE}/v1/pdf?url=https://example.com/report&format=A4`, { headers: h });
const pdfBuf = Buffer.from(await pdf.arrayBuffer());

// AI analysis
const analyze = await fetch(`${BASE}/v1/analyze`, {
  method: "POST",
  headers: { ...h, "Content-Type": "application/json" },
  body: JSON.stringify({ url: "https://example.com", prompt: "Summarize the main content" })
});
const { result } = await analyze.json();

The same X-Api-Key header and base URL work across all endpoints. You can build a single TypeScript service class that exposes screenshot, scrape, extract, PDF, and analyze as methods, sharing the API key and base URL from a single configuration object.

Device Emulation and Full-Page Options

TypeScript developers frequently use device emulation to generate mobile previews for CMS platforms or QA dashboards. Pass device=iPhone_15 or device=Pixel_7 as a query parameter alongside the URL. The API returns a screenshot at the correct resolution and user agent for that device without any browser configuration on your end.

Pricing and Getting Started

Free: 200 captures/month, no credit card. Starter at $19/month: 5,000 captures — right for a small SaaS feature. Pro at $79/month: 50,000 captures — for OG image generators or monitoring pipelines. Business at $299/month: 500,000 captures — for large-scale data and media operations.

Sign up at snapapi.pics, grab your key, and make your first TypeScript screenshot call in under five minutes. Full TypeScript type definitions ship with the snapapi-js npm package at github.com/Sleywill/snapapi-js.

Error Handling and Retry in TypeScript

A production-grade TypeScript SnapAPI integration should handle rate limits and transient errors without crashing. The following wrapper adds typed error handling and exponential backoff using only standard TypeScript — no extra libraries required:

async function snapWithRetry(url: string, retries = 3): Promise<Buffer> {
  for (let attempt = 0; attempt <= retries; attempt++) {
    const res = await fetch(
      `https://api.snapapi.pics/v1/screenshot?url=${encodeURIComponent(url)}`,
      { headers: { "X-Api-Key": process.env.SNAPAPI_KEY! } }
    );
    if (res.ok) return Buffer.from(await res.arrayBuffer());
    if (res.status === 429) {
      const retryAfter = Number(res.headers.get("Retry-After") ?? 5);
      await new Promise(r => setTimeout(r, retryAfter * 1000));
      continue;
    }
    if (res.status >= 500 && attempt < retries) {
      await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));
      continue;
    }
    throw new Error(`SnapAPI ${res.status}: ${await res.text()}`);
  }
  throw new Error("Max retries exceeded");
}

This handles 429 by waiting the exact duration from the Retry-After header, and 5xx by doubling the wait time on each retry attempt. The function throws a typed error on 4xx responses other than 429, making it easy to catch and log bad parameter errors separately from transient failures.

Ready to build? Register at snapapi.pics for 200 free captures per month — no credit card required. The MCP server at npm install -g snapapi-mcp connects SnapAPI directly to your AI coding assistant so you can trigger captures from Claude Code or Cursor.

TypeScript SDK and MCP Server

The snapapi-js npm package ships with full TypeScript type definitions for all endpoints. The snapapi-mcp npm package exposes SnapAPI as an MCP server, connecting it to Claude Code, Cursor, VS Code with Copilot, and other AI coding tools. Install with npm install -g snapapi-mcp and add your API key to the MCP configuration — your AI assistant can then trigger screenshots and scrapes directly from the editor.

typescript screenshot api node deno bun edge cloudflare workers nextjs screenshot