Screenshot API Integration with Vue.js: Complete Guide
Vue.js applications often need to generate screenshots of pages, export dashboard views as images, or capture user-generated content. Rather than shipping a headless browser with your backend, SnapAPI provides a simple REST API that Vue.js apps can call directly to capture any URL. This guide covers every integration pattern from simple composables to Pinia store integration.
Basic Vue Composable
Create a reusable composable at src/composables/useSnapAPI.js:
import { ref } from "vue"
export function useSnapAPI() {
const loading = ref(false)
const error = ref(null)
async function screenshot(url, options = {}) {
loading.value = true
error.value = null
try {
const params = new URLSearchParams({
access_key: import.meta.env.VITE_SNAPAPI_KEY,
url,
response_type: "json",
...options
})
const res = await fetch(`https://snapapi.pics/api/screenshot?${params}`)
if (!res.ok) throw new Error("SnapAPI error " + res.status)
const data = await res.json()
return data.url
} catch (e) {
error.value = e.message
return null
} finally {
loading.value = false
}
}
return { screenshot, loading, error }
}
Screenshot Button Component
Use the composable in a Vue component that lets users capture the current page:
<template>
<div>
<button @click="capture" :disabled="loading">
{{ loading ? "Capturing..." : "Download Screenshot" }}
</button>
<img v-if="imgUrl" :src="imgUrl" alt="Screenshot" />
<p v-if="error" class="error">{{ error }}</p>
</div>
</template>
<script setup>
import { ref } from "vue"
import { useSnapAPI } from "@/composables/useSnapAPI"
const { screenshot, loading, error } = useSnapAPI()
const imgUrl = ref(null)
async function capture() {
imgUrl.value = await screenshot(window.location.href, { width: 1280, full_page: true })
}
</script>
Pinia Store for Screenshot Management
import { defineStore } from "pinia"
export const useScreenshotStore = defineStore("screenshots", {
state: () => ({ captures: [], loading: false, error: null }),
actions: {
async capture(url, label) {
this.loading = true
const params = new URLSearchParams({
access_key: import.meta.env.VITE_SNAPAPI_KEY,
url, response_type: "json", width: 1280
})
const res = await fetch(`https://snapapi.pics/api/screenshot?${params}`)
const data = await res.json()
this.captures.push({ url, label, imgUrl: data.url, capturedAt: new Date() })
this.loading = false
}
}
})
Nuxt.js Server-Side Integration
For Nuxt.js applications, keep the API key server-side using a server route to proxy SnapAPI calls. Create server/api/screenshot.get.js:
export default defineEventHandler(async (event) => {
const { url, ...opts } = getQuery(event)
if (!url) throw createError({ statusCode: 400, message: "url required" })
const config = useRuntimeConfig()
const params = new URLSearchParams({
access_key: config.snapApiKey, url, response_type: "json", ...opts
})
const res = await $fetch(`https://snapapi.pics/api/screenshot?${params}`)
return res
})
In nuxt.config.ts add your key to runtimeConfig:
export default defineNuxtConfig({
runtimeConfig: {
snapApiKey: process.env.SNAPAPI_KEY,
public: {}
}
})
PDF Export from Vue Dashboard
Export any authenticated dashboard view as a PDF by proxying the request server-side with session credentials:
// server/api/export-pdf.post.js
export default defineEventHandler(async (event) => {
const { dashboardUrl, sessionCookie } = await readBody(event)
const config = useRuntimeConfig()
const params = new URLSearchParams({
access_key: config.snapApiKey,
url: dashboardUrl,
format: "pdf",
headers: JSON.stringify({ Cookie: sessionCookie })
})
const res = await fetch(`https://snapapi.pics/api/screenshot?${params}`)
const buffer = await res.arrayBuffer()
setResponseHeader(event, "Content-Type", "application/pdf")
return buffer
})
Error Handling and Retry Logic
Add retry logic to your composable for production resilience. Network hiccups and occasional API timeouts are a reality in any integration. A simple retry with exponential backoff handles transient failures gracefully:
async function screenshotWithRetry(url, options = {}, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await screenshot(url, options)
} catch (e) {
if (i === attempts - 1) throw e
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)))
}
}
}
Environment Configuration
Store your SnapAPI key in a .env file at your project root and reference it via import.meta.env.VITE_SNAPAPI_KEY in Vue components. Never commit .env files to version control. For Nuxt.js, use the runtimeConfig server-side approach shown above to keep the key fully server-side and out of the browser bundle. For Vue SPA deployments on Vercel or Netlify, configure the environment variable in your project settings dashboard and it will be available at build time.
Get Started Free
SnapAPI offers 200 screenshot API calls per month on the free tier with no credit card. Create your account, copy your API key into your .env file, and your first Vue.js screenshot integration can be working within the hour. Paid plans start at $19 per month for 5,000 screenshots and scale to custom enterprise tiers.
Get Free API Key