Screenshot API for Astro Sites

Generate OG images, PDFs, and screenshots from your Astro website. Works with Astro endpoints, SSR mode, and any deployment target including Cloudflare and Vercel.

Start Free — 200 Screenshots/mo

Astro and Screenshot Generation

Astro's component island architecture makes it one of the fastest frameworks for content sites, but screenshot and OG image generation adds complexity. Static sites can't run server code, and even Astro's SSR mode (with adapters for Vercel, Cloudflare, or Node) doesn't support running Chromium inside the function. SnapAPI solves this: a single fetch call from any Astro API endpoint or server-side page returns a CDN-hosted screenshot or OG image.

Astro API Endpoint for Screenshots

// src/pages/api/screenshot.ts
import type { APIRoute } from "astro";

export const GET: APIRoute = async ({ url }) => {
  const target = url.searchParams.get("url");
  if (!target) return new Response("url required", { status: 400 });

  const params = new URLSearchParams({
    access_key: import.meta.env.SNAPAPI_KEY,
    url: target,
    width: "1280",
    full_page: "true",
  });
  const res = await fetch(`https://snapapi.pics/v1/screenshot?${params}`);
  const data = await res.json();
  return new Response(JSON.stringify({ url: data.url }), {
    headers: { "Content-Type": "application/json" },
  });
};

OG Image Generation for Astro Content Collections

Astro Content Collections power most modern Astro blogs and documentation sites. Generate OG images for every post in your collection by creating a dedicated OG template page and calling SnapAPI during build or on-demand in SSR mode.

// src/pages/og/[slug].ts (SSR route)
import type { APIRoute } from "astro";
import { getCollection } from "astro:content";

export const GET: APIRoute = async ({ params }) => {
  const posts = await getCollection("blog");
  const post = posts.find(p => p.slug === params.slug);
  if (!post) return new Response("Not found", { status: 404 });

  const templateUrl = `${import.meta.env.SITE}/og-template/${params.slug}`;
  const snapParams = new URLSearchParams({
    access_key: import.meta.env.SNAPAPI_KEY,
    url: templateUrl,
    width: "1200",
    height: "630",
    format: "png",
  });
  const res = await fetch(`https://snapapi.pics/v1/screenshot?${snapParams}`);
  const { url } = await res.json();
  return Response.redirect(url, 302);
};

Setting OG Meta Tags in Astro Layouts

---
// src/layouts/BlogPost.astro
const { title, slug } = Astro.props;
const ogImageUrl = `${Astro.site}og/${slug}`;
---

  
    {title}
    
    
    
    
  
  
    
  

Static Site Generation: Pre-building OG Images

For pure static Astro sites (no SSR adapter), generate OG images at build time using a build script that calls SnapAPI for each content collection entry. Store the resulting CDN URLs in a JSON file that your Astro pages import at build time.

// scripts/generate-og-images.mjs (run during CI/CD before astro build)
import { readdir, writeFile } from "fs/promises";

const posts = await getAstroContentCollection();
const ogMap = {};

for (const post of posts) {
  const url = `https://yoursite.com/og-template/${post.slug}`;
  const params = new URLSearchParams({
    access_key: process.env.SNAPAPI_KEY, url, width: "1200", height: "630"
  });
  const res = await fetch(`https://snapapi.pics/v1/screenshot?${params}`);
  const { url: ogUrl } = await res.json();
  ogMap[post.slug] = ogUrl;
  console.log(`Generated OG for: ${post.slug}`);
}

await writeFile("src/data/og-images.json", JSON.stringify(ogMap));

Astro + Cloudflare Workers

The Astro Cloudflare adapter deploys your SSR routes to Cloudflare Workers. SnapAPI works perfectly in this environment — it is just a fetch call, which is fully supported on Cloudflare Workers. Set SNAPAPI_KEY in your Cloudflare environment variables via wrangler CLI or the Cloudflare dashboard.

Pricing

Free: 200/mo. Starter: $19/mo (5K). Growth: $79/mo (50K). Works on every Astro deployment target. Start free today.

Get Your Free API Key

Why Astro Developers Choose SnapAPI

Astro's island architecture means you only ship JavaScript where you need it. SnapAPI fits perfectly into that philosophy. Our REST API generates screenshots server-side during your build or at request time, so zero client-side JavaScript is required for screenshot functionality. You get rich visual previews without bloating your client bundle.

Whether you're building a portfolio that previews linked projects, a blog that auto-generates Open Graph images, or a SaaS dashboard showing customer site thumbnails, SnapAPI handles it in a single HTTP call from your Astro API routes or SSR endpoints.

Using SnapAPI in Astro API Routes

Astro 2+ supports file-based API routes under src/pages/api/. Here's a complete screenshot endpoint:

// src/pages/api/screenshot.ts
import type { APIRoute } from 'astro';

export const GET: APIRoute = async ({ url }) => {
  const target = url.searchParams.get('url');
  if (!target) return new Response('Missing url param', { status: 400 });

  const snap = new URL('https://api.snapapi.pics/v1/screenshot');
  snap.searchParams.set('access_key', import.meta.env.SNAPAPI_KEY);
  snap.searchParams.set('url', target);
  snap.searchParams.set('format', 'png');
  snap.searchParams.set('width', '1280');

  const res = await fetch(snap.toString());
  if (!res.ok) return new Response('Screenshot failed', { status: 502 });

  return new Response(res.body, {
    headers: { 'Content-Type': 'image/png', 'Cache-Control': 'public, max-age=86400' }
  });
};

Static Site Generation: Build-Time Screenshots

One of Astro's superpowers is static generation. You can pre-generate screenshots for every page during astro build and ship them as static assets. No API call needed at runtime, no cold starts, no latency for end users. The build hook approach lets you snapshot every route and store the results alongside your static files.

Content Collections + Auto OG Images

Astro's content collections let you define typed frontmatter for Markdown/MDX files. Combine that with SnapAPI's screenshot endpoint and you get automatic social cards for every blog post. Generate a clean Open Graph image from a template URL, cache it during build, and reference it in your meta tags. No canvas library, no ImageMagick, no custom fonts pipeline.

// src/pages/og/[...slug].png.ts
import type { APIRoute } from 'astro';
import { getCollection } from 'astro:content';

export async function getStaticPaths() {
  const posts = await getCollection('blog');
  return posts.map(p => ({ params: { slug: p.slug }, props: { post: p } }));
}

export const GET: APIRoute = async ({ props }) => {
  const { post } = props;
  const ogUrl = encodeURIComponent('https://yoursite.com/og-template/' + post.slug);
  const res = await fetch(
    'https://api.snapapi.pics/v1/screenshot?access_key=' + import.meta.env.SNAPAPI_KEY +
    '&url=' + ogUrl + '&width=1200&height=630&format=png'
  );
  return new Response(res.body, { headers: { 'Content-Type': 'image/png' } });
};

Environment Variables in Astro

Astro splits env vars into public (prefixed PUBLIC_) and server-only. Your SnapAPI key should never be public. Keep it server-only and reference it as import.meta.env.SNAPAPI_KEY in server-only files like API routes, SSR pages, and build hooks. Never import it inside a .astro component that renders on the client side.

Caching Strategy for Astro Projects

Screenshots are expensive to generate, so cache aggressively. In Astro SSR mode, use a KV store or simple in-memory cache keyed by the target URL and a hash of parameters. For static builds, the file system is your cache — only regenerate screenshots that are missing or older than your TTL. SnapAPI's fast Chromium pipeline means even a cache miss stays well under typical serverless timeouts.

Comparing Screenshot APIs for Astro

SnapAPI stands out for Astro projects for several reasons. First, the free tier (200 captures/month) is more than enough to prototype and launch. Second, the API is truly RESTful with predictable URLs — easy to cache at the CDN layer with Astro's built-in caching headers. Third, response times are fast enough to use in SSR mode without a loading state for most pages. Competitors like ScreenshotOne and Urlbox offer similar features but at 3x to 5x the price for equivalent volume.

Pricing That Scales With Astro Projects

Most Astro sites start small. SnapAPI's free tier gives you 200 screenshots per month — more than enough for a personal portfolio or small blog. When you grow, upgrade to the 19 dollar per month plan for 5,000 captures. Agency or SaaS builders handling dozens of client sites fit comfortably on the 79 dollar per month plan. All plans include full-page captures, PDF generation, and the scrape and extract endpoints.

Astro + SnapAPI FAQ

Does SnapAPI work with Astro View Transitions? Yes. Since screenshots are generated server-side from a full URL, View Transitions only affect the client-side navigation experience and do not impact the screenshot output. SnapAPI captures the final rendered state of any URL you pass.

Can I use SnapAPI with Astro's hybrid rendering mode? Absolutely. Hybrid mode lets you mix static and server-rendered pages. Use the screenshot endpoint in your SSR routes for dynamic captures and in build hooks for static pre-generation. Both patterns work seamlessly.

What about Astro DB? If you store screenshot metadata in Astro DB, you can implement a simple cache layer: check the DB for a cached screenshot URL before calling SnapAPI, and only generate a fresh one if the cache entry is missing or expired. This dramatically reduces API usage and speeds up response times for repeat requests.

Is there an Astro integration package? Not yet officially, but SnapAPI's REST API is simple enough that you need no wrapper. A single fetch call is all it takes. Community integrations are welcome — check the GitHub org at github.com/Sleywill for the JavaScript SDK which works in any Node.js environment including Astro's server runtime.

Ready to add screenshots to your Astro project? Sign up at snapapi.pics — free tier, no credit card required, 200 captures per month.