arrow_back Back to blog
Tutorials February 15, 2026 8 min read

Screenshot APIs Explained: A Developer's Guide

If you’ve ever needed to generate a thumbnail of a webpage, produce a PDF from a URL, or monitor how your site looks across different viewports, you’ve probably run into the same question: do I build this myself, or is there a better way?

Screenshot APIs exist to answer that question. They take care of the hard parts — spinning up headless browsers, handling JavaScript rendering, managing timeouts and retries — so you can capture any webpage with a single HTTP request. This guide walks through how they work, when to use one over a DIY setup, and how to get started with len.sh in under five minutes.

What Is a Screenshot API?

A screenshot API is a web service that accepts a URL and returns an image (or PDF) of that webpage as it would appear in a real browser. You call the API, the service loads the page in a headless browser, renders all the JavaScript and CSS, and hands you back a screenshot.

The appeal is straightforward: you get a fully-rendered screenshot without managing any browser infrastructure yourself. No installing Chromium, no maintaining Puppeteer versions, no worrying about memory leaks from long-running browser processes.

Screenshot APIs have become increasingly common as the web has shifted toward JavaScript-heavy single-page applications. A simple HTTP request or curl command can’t render a React or Next.js app — you need an actual browser. That’s what a screenshot API provides, as a service.

How Screenshot APIs Work Under the Hood

When you call a screenshot API, a lot happens in the background in a fraction of a second.

1. The request lands on the API server. Your HTTP request arrives with parameters: the target URL, viewport dimensions, output format, and any other options you’ve specified.

2. A headless browser is launched (or reused from a pool). The service spins up a headless instance of Chromium or a similar rendering engine. “Headless” means it runs without a visible display — it can render pages fully, including JavaScript execution and CSS animations, but there’s no GUI.

3. The page loads. The browser navigates to your target URL, downloads all resources (HTML, CSS, JS, images, fonts), executes JavaScript, and renders the final layout. This is the same process your desktop browser goes through, just automated.

4. Wait strategies are applied. Some pages need extra time — JavaScript frameworks that render client-side, lazy-loaded images, animations. A good screenshot API lets you specify a delay or wait for a specific DOM event before capturing.

5. The screenshot is taken. The browser captures the rendered viewport (or the full page, depending on your settings) and returns the image in your requested format.

6. The image is returned. The binary image data comes back in the API response, ready to save, store in S3, or pipe directly to your users.

The whole process typically takes between 1–5 seconds depending on the complexity of the target page and your chosen parameters.

DIY vs. Using a Screenshot API

If you’re comfortable with Node.js, you might be tempted to spin up Puppeteer and call it a day. Here’s an honest look at both approaches.

The DIY route: Puppeteer or Playwright

Self-hosting screenshot generation is entirely possible. Puppeteer and Playwright are excellent tools, and for low-volume, internal use cases they can work well. A basic setup looks like this:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
const screenshot = await page.screenshot({ type: 'png' });
await browser.close();

Simple enough. But the problems start when you move beyond a single developer environment:

  • Infrastructure overhead. Chromium is heavy. Each browser instance can use 200–500 MB of RAM. Running this at scale means provisioning servers specifically for browser workloads.
  • Concurrency. What happens when 100 users request screenshots at once? You need a browser pool, a queue, and logic to manage it all.
  • Maintenance. Puppeteer and Playwright release updates regularly. Chromium versions change. Pages that worked last month start timing out. Someone has to own this.
  • Deployment complexity. Getting headless Chromium running reliably in Docker, on Lambda, or in a Kubernetes pod is non-trivial. Font rendering, sandbox flags, and shared memory limits are common pain points.
  • Reliability. Browsers crash. Memory leaks happen. You need monitoring and restart logic.

None of this is insurmountable, but it’s a meaningful engineering investment. If screenshot generation isn’t core to your product, that engineering time is probably better spent elsewhere.

The managed API route

A screenshot API abstracts all of that away. You make an HTTP request, you get an image. The provider handles browser infrastructure, scaling, reliability, and updates.

The tradeoff is cost and control. You’re paying per request rather than running your own servers, and you’re working within the API’s feature set. For most use cases, that’s a very reasonable trade.

Key Features to Look For in a Screenshot API

Not all screenshot APIs are equal. Here’s what to evaluate when choosing one:

Full-page capture. Does it support capturing the entire scrollable page, not just the viewport? Useful for generating comprehensive thumbnails or PDFs.

Viewport control. Can you set width and height to simulate different devices? Mobile, tablet, and desktop rendering can look very different.

Output formats. PNG for lossless quality, JPEG for smaller file sizes, WebP for modern use cases, PDF for documents. Having all four gives you flexibility.

Wait/delay options. Can you add a fixed delay (e.g., wait 2 seconds after load) or wait for specific conditions? Essential for JavaScript-heavy pages.

Reliability and uptime. Check the provider’s status page and SLA. Screenshot failures can cascade into user-facing issues.

Pricing model. Per-request, per-month, or tiered? Make sure the model fits your usage patterns.

Speed. Average response time matters, especially if you’re generating screenshots synchronously in a user-facing flow.

Getting Started with len.sh

len.sh provides a simple REST API for capturing screenshots. Here’s how to go from zero to your first screenshot.

Step 1: Get your API key

Sign up at len.sh and grab your API key from the dashboard. You’ll use it as a query parameter on every request.

Step 2: Your first screenshot with curl

The simplest possible request captures a PNG of a URL at the default viewport size:

curl "https://api.len.sh/v1/screenshot?url=https://example.com&api_key=YOUR_API_KEY" \
  --output screenshot.png

That’s it. Open screenshot.png and you’ll see a rendered screenshot of https://example.com.

Step 3: Customizing the capture

The API accepts several query parameters to control the output:

ParameterTypeDescription
urlstringThe URL to capture (required)
widthintegerViewport width in pixels (default: 1280)
heightintegerViewport height in pixels (default: 800)
formatstringOutput format: png, jpeg, webp, or pdf
full_pagebooleanCapture the full scrollable page
delayintegerWait time in milliseconds before capture

Here’s a more complete example — a full-page WebP screenshot of a documentation site, captured at 1440px wide with a 1-second delay to let animations settle:

curl "https://api.len.sh/v1/screenshot?url=https://docs.example.com&width=1440&height=900&format=webp&full_page=true&delay=1000&api_key=YOUR_API_KEY" \
  --output screenshot.webp

Step 4: Using the API in JavaScript

Here’s how you’d capture a screenshot and upload it to your storage layer in a Node.js application:

async function captureScreenshot(targetUrl) {
  const params = new URLSearchParams({
    url: targetUrl,
    width: '1280',
    height: '800',
    format: 'png',
    full_page: 'true',
    delay: '500',
    api_key: process.env.LENSH_API_KEY,
  });

  const response = await fetch(
    `https://api.len.sh/v1/screenshot?${params}`
  );

  if (!response.ok) {
    throw new Error(`Screenshot failed: ${response.statusText}`);
  }

  const imageBuffer = await response.arrayBuffer();
  return Buffer.from(imageBuffer);
}

// Usage
const screenshot = await captureScreenshot('https://yoursite.com');
// Save to disk, upload to S3, return to client, etc.

Step 5: Using the API in Python

For Python, the requests library keeps it clean:

import requests
import os

def capture_screenshot(target_url: str, output_path: str) -> None:
    params = {
        "url": target_url,
        "width": 1280,
        "height": 800,
        "format": "jpeg",
        "full_page": "true",
        "delay": 500,
        "api_key": os.environ["LENSH_API_KEY"],
    }

    response = requests.get(
        "https://api.len.sh/v1/screenshot",
        params=params,
        stream=True,
    )
    response.raise_for_status()

    with open(output_path, "wb") as f:
        for chunk in response.iter_content(chunk_size=8192):
            f.write(chunk)

capture_screenshot("https://yoursite.com/blog", "blog-screenshot.jpg")

Common Use Cases

Screenshot APIs show up in a surprising number of real-world applications:

Open Graph image generation. Render a dynamic OG image for each blog post or product page, based on a styled template URL, then serve the screenshot as the og:image meta tag.

Visual monitoring. Capture screenshots of your site on a schedule and compare them to detect unexpected layout regressions or third-party widget changes.

Link preview thumbnails. When a user shares a URL in your app, show a live thumbnail of the linked page — the same experience users expect from Slack, Notion, or Twitter.

PDF generation from URLs. Use format=pdf to turn any webpage into a downloadable PDF, useful for invoices, reports, or any print-formatted content.

Automated visual testing. Integrate screenshot capture into your CI pipeline to catch visual regressions before they reach production.

Content archiving. Preserve the visual state of pages at a point in time — useful for legal, compliance, or research purposes.

Conclusion

Screenshot APIs remove a genuinely hard infrastructure problem from your plate. Whether you’re building a monitoring tool, generating thumbnails, or automating PDF exports, managing headless browser infrastructure is rarely worth doing yourself when a reliable API exists.

len.sh is designed to be as simple as possible to start with — a single curl command gets you a screenshot in seconds — while supporting the full range of options you’ll need as requirements grow: viewport control, full-page capture, multiple output formats, and configurable wait times.

If you haven’t already, sign up for a free account and run your first API call. The free tier lets you explore the API before committing to anything, and the documentation covers every parameter in detail.

One HTTP request. Any URL. Any format. That’s the idea.

Try len.sh for free

Start capturing screenshots with a simple API call. No credit card required.