Back to blog
TutorialsNode.jsAPIGetting started

Capture screenshots from Node.js with nothing but fetch

No SDK required. A copy-paste helper for Node 18+, with typed options, error handling and downloading the file.

Ruby Le
Ruby Le
Project Manager
· Jun 24, 2026· 2 min read

Node 18 and later ship with a global fetch, which is all you need to call Snapopa. This tutorial builds a small helper you can drop into any project.

1. Get an API key

Create a key under API Keys in the dashboard and export it:

export SNAPOPA_API_KEY="sk_..."

2. The helper

type CaptureOptions = {
  url: string
  format?: 'png' | 'jpeg' | 'webp' | 'pdf'
  isFullPage?: boolean
  viewport?: { width?: number; height?: number }
}

export async function capture(options: CaptureOptions) {
  const res = await fetch('https://api.snapopa.com/capture', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.SNAPOPA_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(options),
  })

  const body = await res.json()
  if (!res.ok || !body.success) {
    throw new Error(body.error?.message ?? `Capture failed with ${res.status}`)
  }
  return body.data as { uuid: string; fileUrl: string; fromCache: boolean }
}

3. Use it

const shot = await capture({ url: 'https://example.com', format: 'webp', isFullPage: true })
console.log(shot.fileUrl)

4. Save the file locally

import { writeFile } from 'node:fs/promises'

const file = await fetch(shot.fileUrl)
await writeFile('example.webp', Buffer.from(await file.arrayBuffer()))

Skipping the JSON step

If you only want the bytes, set responseType to file and the API returns the image directly:

const res = await fetch('https://api.snapopa.com/capture', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SNAPOPA_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ url: 'https://example.com', responseType: 'file' }),
})
await writeFile('example.png', Buffer.from(await res.arrayBuffer()))

Next steps

  • Add responseCache to avoid paying twice for the same page - see response caching.
  • Try the same request in the dashboard Playground, which can also generate this code for you.
Try Snapopa

Reading about screenshots? Try the API.

100 free tokens on signup. No credit card. One request is all it takes.

$ curl https://api.snapopa.com/capture \
    -H "Authorization: Bearer sk_•••" \
    -d '{"url":"https://stripe.com"}'

✓ 200 OK
{ "data": { "fileUrl": "https://cdn.snapopa.com/…" } }