JavaScript Screenshot API
Capture website screenshots from the browser using client-side JavaScript. Call the Screenshotly API with the Fetch API from React, Vue, Angular, or vanilla JS — no server required for basic workflows. This guide covers browser JavaScript screenshot API usage, async/await patterns, error handling, blob URLs for display, and best practices for CORS and API key security when calling from the client.
Quick Start
Install dependencies
Install via npm or use the native Fetch API — no extra packages needed for modern browsers.
Get your API key
Sign up for Screenshotly and get your API key from the dashboard.
Copy the code example
Use our JavaScript code example as a starting point.
Customize and integrate
Modify the code to fit your specific use case and requirements.
Code Example
// JavaScript/Browser — proxy through your backend in production
const captureScreenshot = async (url) => {
const response = await fetch('https://api.screenshotly.app/screenshot', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY', // ⚠️ Use a backend proxy in production
'Content-Type': 'application/json',
},
body: JSON.stringify({
url,
device: 'desktop',
format: 'png',
}),
});
const blob = await response.blob();
return URL.createObjectURL(blob);
};When to Use JavaScript with Screenshotly
Use the JavaScript integration for browser-side, client-side screenshot capture. Call the API from React, Vue, Angular, or vanilla JS running in the user's browser. Ideal for interactive screenshot tools in SPAs, link preview generators embedded in web apps, and real-time visual monitoring dashboards that run entirely in the browser.
JavaScript Best Practices
Proxy API requests through your own backend in production to avoid exposing your API key in client-side browser code.
Use AbortController to cancel in-flight requests when a user navigates away or starts a new capture.
Convert the response blob to a data URL with FileReader.readAsDataURL() when you need to embed the screenshot inline.
For React/Next.js client components, wrap the API call in a custom hook with loading, error, and data states for cleaner component code.
JavaScript: Production Notes
The single biggest mistake on client-side JavaScript integration is embedding the API key in a public bundle. Every `fetch()` call from the browser sends the Authorization header over the wire where any user can open DevTools and copy it. The production pattern is always a thin backend proxy: your React/Vue/Next.js app calls your own `/api/screenshot` route, which adds the Bearer token server-side and forwards the request.
For SPAs that capture on user action, use `AbortController` to cancel the request when the user navigates away or triggers a new capture. Without cancellation, stale captures from an abandoned navigation can race-condition into the UI after the user has moved on.
Error Handling Recipes
Concrete strategies for each failure mode. Do not silently swallow errors — surface them to your monitoring so the pipeline is observable.
HTTP 401 / 403
Surface as a developer-facing error, not user-facing. In production, this usually means the backend proxy failed to inject the token — log the env var name, not the value.
HTTP 429
Read Retry-After header and retry with exponential backoff (1s, 2s, 4s, 8s max). If user-initiated, show a "high demand, retrying..." state.
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '1', 10);
await new Promise(r => setTimeout(r, retryAfter * 1000));
return captureScreenshot(url);
}Network timeout
Native fetch has no timeout. Use AbortController with a 30-second timeout for full-page captures, 10-second for viewport captures.
Production Hardening Checklist
The difference between dev code and prod code. Work through these before putting JavaScript captures on a critical path.
- API key lives in a server-side env var only — never in the client bundle or localStorage.
- Backend proxy endpoint validates the caller (auth, per-user rate limit) before forwarding.
- AbortController cancels in-flight captures on navigation or new capture trigger.
- Blob URLs are revoked with URL.revokeObjectURL() when no longer needed.
- Captures are debounced when bound to user input (URL field typing).
- A loading state handles captures >5s so users do not think the app froze.
Rate-Limit Strategy
Enforce per-user rate limits in your proxy endpoint (e.g. 10 captures/minute/user) before the request reaches Screenshotly. This protects your paid quota from abusive users and keeps API usage predictable. Use a sliding-window counter in Redis.
When JavaScript isn't the right fit
JavaScript works well for most capture workloads, but these patterns are legitimate reasons to pick a different stack:
- You are building a static site with no backend — you cannot hide the API key safely and need to either add a serverless proxy route (Vercel/Netlify functions) or skip client-initiated capture entirely.
- Your app is a pure mobile React Native or Ionic app — the browser Fetch patterns need adaptation for the native environment; use a backend-issued presigned capture URL instead.
- You need synchronous in-page capture without any backend. That is the one workflow a browser extension serves better than a JS-calls-API pattern.
Want a step-by-step walkthrough?
Read the full JavaScript tutorial →API Reference
POST /api/screenshotBearer tokenapplication/jsonFrequently Asked Questions
How do I handle CORS when calling the screenshot API from the browser?
The Screenshotly API supports CORS for browser requests. Make sure to include your API key in the Authorization header and use HTTPS. For production apps, consider proxying requests through your backend for better security.
Can I capture screenshots in React applications?
Yes! Use the fetch API or libraries like axios to call our screenshot API from React components. You can display captured screenshots using blob URLs or save them to your backend storage.
What's the best way to handle errors in JavaScript?
Always wrap API calls in try-catch blocks and check response.ok before processing. Common errors include 401 (invalid API key), 429 (rate limit exceeded), and 400 (invalid parameters).
How do I convert the response to different formats?
The API returns binary image data. Use response.blob() for browser display, response.arrayBuffer() for processing, or response.buffer() in Node.js for file operations.
Start building with JavaScript
Get your API key and start capturing screenshots in minutes.
Other Languages
Node.js
Server-side screenshot capture with Node.js — for backend services, Express/Fastify APIs, CLI tools, and automation scripts. This guide covers the Node.js screenshot API for server-side use only: streaming responses to disk or S3, Express screenshot middleware, cron jobs, and integrating with Bull/BullMQ for batch processing. Keep API keys on the server where they belong.
Python
Integrate screenshot capture into Python applications using the requests library or httpx. Ideal for data pipelines, Django/Flask web apps, automation scripts, and web scraping projects. Includes examples for synchronous and async requests, saving images to files, and handling rate limits with exponential backoff.
PHP
Add screenshot capabilities to PHP applications using cURL or Guzzle HTTP. Perfect for WordPress plugins, Laravel apps, and REST-based web services. Covers authentication, error handling, saving to local storage or S3, and integrating with Laravel queues for background processing.
Ruby
Screenshot API integration for Ruby and Rails applications using Net::HTTP or the Faraday gem. Streamline visual testing, content generation, and background job processing with Sidekiq. Includes production patterns for retry logic, file uploads to Active Storage, and integration with Rails controller actions.