Back to Blog
Guide February 25, 2026 · 4 min read

How to Take Screenshots in Django and Flask (Without Selenium)

Adding screenshot functionality to a Python web app usually means managing ChromeDriver, debugging WebDriverException in production. Here's the lighter path: one HTTP request, one binary response.

Adding screenshot functionality to a Python web app typically means managing a headless browser: installing ChromeDriver, keeping it in sync with Chrome, debugging WebDriverException in production. Selenium and Playwright solve the problem but add significant operational weight.

Here's the lighter path: one HTTP request, one binary response.

Django view

import requests
from django.http import HttpResponse

def screenshot(request):
    url = request.GET.get('url', 'https://example.com')

    res = requests.post(
        'https://pagebolt.dev/api/v1/screenshot',
        headers={'x-api-key': settings.PAGEBOLT_API_KEY},
        json={'url': url, 'fullPage': True, 'blockBanners': True}
    )

    return HttpResponse(res.content, content_type='image/png')

Flask route

import requests
from flask import Flask, request, send_file
import io

app = Flask(__name__)

@app.route('/screenshot')
def screenshot():
    url = request.args.get('url', 'https://example.com')

    res = requests.post(
        'https://pagebolt.dev/api/v1/screenshot',
        headers={'x-api-key': app.config['PAGEBOLT_API_KEY']},
        json={'url': url, 'fullPage': True, 'blockBanners': True}
    )

    return send_file(io.BytesIO(res.content), mimetype='image/png')

Save to disk (scripts, management commands)

import requests

def capture(url, output_path):
    res = requests.post(
        'https://pagebolt.dev/api/v1/screenshot',
        headers={'x-api-key': 'YOUR_API_KEY'},
        json={
            'url': url,
            'fullPage': True,
            'blockBanners': True,
            'format': 'png'
        }
    )
    with open(output_path, 'wb') as f:
        f.write(res.content)

capture('https://yourapp.com', 'screenshot.png')

Common options

# Mobile viewport
{'url': url, 'viewportDevice': 'iphone_14_pro'}

# Dark mode
{'url': url, 'darkMode': True, 'fullPage': True}

# From HTML string (e.g. a rendered Django template)
html = render_to_string('report_template.html', context)
{'html': html, 'format': 'png'}

# JPEG with quality
{'url': url, 'format': 'jpeg', 'quality': 85}

The html parameter is useful for capturing rendered Django or Jinja2 templates without a running server — handy for generating preview images of reports, emails, or documents.

The upgrade: record a narrated video

Once screenshot infrastructure is in place, the same API handles narrated browser recordings:

res = requests.post(
    'https://pagebolt.dev/api/v1/video',
    headers={'x-api-key': 'YOUR_API_KEY'},
    json={
        'steps': [
            {'action': 'navigate', 'url': 'https://yourapp.com', 'note': 'Open the app'},
            {'action': 'click', 'selector': '#get-started', 'note': 'Get started'}
        ],
        'audioGuide': {
            'enabled': True,
            'voice': 'nova',
            'script': "Here's the app. {{1}} {{2}} One click to begin."
        },
        'pace': 'slow',
        'frame': {'enabled': True, 'style': 'macos'}
    }
)
with open('demo.mp4', 'wb') as f:
    f.write(res.content)

Same request pattern, binary MP4 response, no browser process.

Deployment

No Selenium, no ChromeDriver, no browser binary. Works on any Python hosting — Heroku, Render, Railway, AWS Lambda (with the requests layer), or bare metal. Add PAGEBOLT_API_KEY to your environment variables and deploy as normal.

Get Started Free

100 requests/month, no credit card

Add screenshots to your Django or Flask app in minutes — no ChromeDriver, no Selenium, no browser to manage.

Get Your Free API Key →