Screenshot API for Django

Add screenshot capture, PDF generation, and web scraping to your Django application with a simple REST API call. No Celery workers for browser automation required.

Start Free — 200 captures/month
Python SDKDjango ViewsCelery ReadyPDF Export

Quick Start: Django + SnapAPI

Install the Python SDK and add your API key to Django settings. Then call the screenshot or PDF endpoint directly from any view, management command, or Celery task.

pip install requests  # or use the snapapi Python SDK

settings.py

import os

SNAPAPI_KEY = os.environ.get("SNAPAPI_KEY", "")
SNAPAPI_BASE_URL = "https://api.snapapi.pics"

Screenshot in a Django View

import requests
from django.conf import settings
from django.http import JsonResponse

def capture_screenshot(request):
    target_url = request.GET.get("url")
    if not target_url:
        return JsonResponse({"error": "url required"}, status=400)

    resp = requests.post(
        f"{settings.SNAPAPI_BASE_URL}/v1/screenshot",
        headers={"X-Api-Key": settings.SNAPAPI_KEY},
        json={
            "url": target_url,
            "format": "png",
            "full_page": True,
            "width": 1280,
        },
        timeout=30,
    )

    if resp.status_code != 200:
        return JsonResponse({"error": "capture failed"}, status=502)

    data = resp.json()
    return JsonResponse({"screenshot_url": data["url"]})

PDF Export in Django (Invoices, Reports)

A common Django use case is exporting model data as a PDF — invoices, order confirmations, reports. The typical pattern: render your data to an HTML template, serve it at a temporary URL, then call SnapAPI to convert it to PDF.

from django.template.loader import render_to_string
from django.http import HttpResponse
import requests, base64

def invoice_pdf(request, invoice_id):
    invoice = get_object_or_404(Invoice, id=invoice_id, user=request.user)

    # Option 1: pass a URL to the HTML invoice page
    invoice_url = request.build_absolute_uri(
        reverse("invoice_html", args=[invoice_id])
    )
    token = generate_signed_token(invoice_id)
    signed_url = f"{invoice_url}?token={token}"

    resp = requests.post(
        "https://api.snapapi.pics/v1/pdf",
        headers={"X-Api-Key": settings.SNAPAPI_KEY},
        json={
            "url": signed_url,
            "format": "A4",
            "margin": "1.5cm",
            "print_background": True,
            "wait_for": ".invoice-ready",
        },
        timeout=30,
    )

    pdf_data = resp.json()
    pdf_response = requests.get(pdf_data["url"])

    response = HttpResponse(pdf_response.content, content_type="application/pdf")
    response["Content-Disposition"] = f'attachment; filename="invoice-{invoice_id}.pdf"'
    return response

Celery Task for Async Screenshot Capture

For non-blocking screenshot generation, wrap the API call in a Celery task. The Django view triggers the task and returns immediately, while the task captures the screenshot and stores the result in your database or cache.

from celery import shared_task
from django.core.cache import cache
import requests

@shared_task(bind=True, max_retries=3)
def capture_site_screenshot(self, url, screenshot_id):
    try:
        resp = requests.post(
            "https://api.snapapi.pics/v1/screenshot",
            headers={"X-Api-Key": settings.SNAPAPI_KEY},
            json={"url": url, "format": "png", "full_page": True},
            timeout=30,
        )
        resp.raise_for_status()
        data = resp.json()

        # Store result in cache for 1 hour
        cache.set(f"screenshot:{screenshot_id}", data["url"], timeout=3600)
        return data["url"]

    except requests.RequestException as exc:
        # Retry with exponential backoff on network errors
        raise self.retry(exc=exc, countdown=2 ** self.request.retries)

Django REST Framework Integration

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, permissions
import requests

class ScreenshotAPIView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request):
        url = request.data.get("url")
        format_ = request.data.get("format", "png")

        if not url:
            return Response({"error": "url is required"}, status=status.HTTP_400_BAD_REQUEST)

        resp = requests.post(
            "https://api.snapapi.pics/v1/screenshot",
            headers={"X-Api-Key": settings.SNAPAPI_KEY},
            json={"url": url, "format": format_, "full_page": True},
            timeout=30,
        )

        if resp.ok:
            return Response(resp.json())
        return Response({"error": "upstream error"}, status=status.HTTP_502_BAD_GATEWAY)

Why Not Use Playwright Directly in Django?

Running Playwright inside a Django process is problematic. Playwright requires an event loop, which conflicts with Django's synchronous request handling. You can work around this with asyncio.run() in views, but Chromium's memory footprint means a few concurrent requests can exhaust your dyno or container. SnapAPI externalizes the browser entirely — your Django app stays stateless, scales horizontally, and never needs a browser binary in your Docker image.

Pricing for Django Applications

The Free plan gives 200 captures per month — suitable for prototyping or low-traffic Django applications. Starter at $19/month covers 5,000 captures (great for SaaS apps with occasional PDF exports). Pro at $79/month covers 50,000 captures. Business at $299/month covers 500,000. All plans use the same API key with no per-endpoint restrictions.

Add Screenshots to Your Django App →

Web Scraping in Django with SnapAPI

Beyond screenshots and PDFs, SnapAPI scrape and extract endpoints are useful for Django applications that pull data from external websites. Competitor price checking, content aggregation, lead enrichment, and monitoring tools all benefit from having a robust scraping layer. Because scraping runs in SnapAPI infrastructure, your Django app stays stateless and you avoid managing Playwright or Scrapy clusters.

import requests
from django.conf import settings

def extract_product_data(product_url):
    resp = requests.post(
        "https://api.snapapi.pics/v1/extract",
        headers={"X-Api-Key": settings.SNAPAPI_KEY},
        json={
            "url": product_url,
            "schema": {"name": "string", "price": "number", "in_stock": "boolean"},
            "stealth": True,
        },
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()

Visual Regression Testing with Django

SnapAPI can be part of your Django test suite for visual regression testing. Capture screenshots of your staging environment before and after deployments, store the image URLs, and compare them to detect unintended visual changes. This is particularly valuable for Django applications with complex templates where CSS or template changes can have far-reaching visual effects that unit tests would not catch.

Handling Rate Limits and Quota in Django

If your Django application sends many screenshot requests, implement a simple quota tracker using the Django cache framework. Store the count of API calls per time window in Redis or Memcached, check before each API call, and surface a clear error when the quota is nearing its limit. This prevents unexpected charges and helps you plan your SnapAPI plan upgrade at the right time. A basic implementation uses cache.get and cache.set with a one-hour timeout key to track hourly call counts across your Django worker processes.

Using SnapAPI in Django Management Commands

Management commands are an excellent place to run batch screenshot or scraping jobs. A nightly python manage.py sync_screenshots command can iterate over a list of URLs stored in your database, capture fresh screenshots via SnapAPI, update the stored image URLs, and log any failures. Because the command runs outside the request/response cycle, you have more generous timeouts and no risk of blocking user-facing requests. Combine with Celery Beat for scheduled execution or with Django-Q for a simpler setup that does not require a separate message broker.

Architecture Summary

The cleanest Django architecture for SnapAPI: store your API key in environment variables via django-environ or python-decouple, create a dedicated capture Django app with a service layer, call the service from views or Celery tasks, and cache results in Redis. This keeps your codebase clean, testable, and decoupled from any specific screenshot provider. If you ever switch APIs, only the service layer needs updating. Sign up free at snapapi.pics and add screenshot capabilities to your Django project today.

Django Screenshot API: Complete Feature Reference

When integrating SnapAPI into your Django project, the following features are available through the same API key across all endpoints. The screenshot endpoint supports PNG, JPEG, and WebP output formats, full-page capture, viewport control, custom CSS and JavaScript injection, and device emulation with over thirty presets including iPhone, Android, and iPad models. The PDF endpoint supports A4 and Letter paper formats, custom margins, print background colors, and a wait-for selector that lets you delay capture until your page signals it is fully rendered. The scrape endpoint returns the full rendered HTML of any URL after JavaScript execution, with optional CSS selector filtering to extract just the elements you need. The extract endpoint uses AI to pull structured JSON from any page based on a schema you define — no CSS selectors required. The analyze endpoint lets you ask natural language questions about a page and receive an AI-generated answer. All endpoints share the same base URL, the same X-Api-Key authentication header, and the same JSON request format. Rate limits are enforced per API key at the account level, and all plans support concurrent requests. The SnapAPI Python SDK wraps these endpoints with typed request and response classes if you prefer a higher-level interface over raw requests calls. Install it with pip install snapapi and set the SNAPAPI_KEY environment variable to get started in your Django project without any additional configuration.

SnapAPI is the fastest way to add screenshot, PDF export, and scraping capabilities to a Django project without touching your infrastructure. The free tier at snapapi.pics gives you 200 captures per month with no credit card — enough to prototype, integrate into your Django views, write tests, and validate the API fits your workflow before committing to a paid plan. Most Django developers complete their first working integration within an afternoon, using the Python requests library and a handful of lines of view code.

Django developers choosing SnapAPI benefit from a clean separation of concerns — your application logic stays in Django, while browser complexity lives in the API. This architectural cleanliness pays dividends as your application grows, keeping deployments simple and your team focused on product rather than browser infrastructure maintenance.

SnapAPI Django integration is production-ready, well-documented, and actively maintained with backward-compatible API updates.