The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →To capture a web page from Django, send a server-side HTTP request to a hosted screenshot API, then return the image or PDF response from a Django view. The example below uses the documented POST /api/v1/screenshot contract with bearer authentication, JSON options, full-page capture and a configurable viewport. Keep the API key on your server; never put it in browser JavaScript.
Choose the capture approach first
| Approach | Best for | Request and output |
|---|---|---|
| Hosted screenshot API | Application features, reports, scheduled jobs and capturing public URLs | GET query parameters or POST JSON; PNG, JPEG, WebP or PDF |
| Official Python SDK | Teams that prefer a package abstraction over HTTP | Install with pip install screenshot-api; the provider documents Django, Flask and FastAPI compatibility |
| Django Selenium screenshots | Visual regression and browser-based tests against your own application | Local test browser controlled by SeleniumTestCase and Django’s screenshot test options |
Use a hosted API when your Django application needs to capture a URL as part of normal runtime work. Use Selenium when the purpose is testing your interface in a controlled browser. They solve related but different problems.
Quick start: a Django view with the REST API
1. Install the HTTP client
pip install requests
The provider also lists an official SDK installable with pip install screenshot-api. Direct HTTP is shown here because it exposes the documented request and response contract without inventing SDK method names.
2. Put the key in server configuration
# settings.py
import os
SCREENSHOT_API_KEY = os.environ["SCREENSHOT_API_KEY"]
Set SCREENSHOT_API_KEY in your process environment or secret manager. The API reference recommends an authorization header. Do not render the key into templates, send it to a browser, or commit it to source control.
#1 Best Overall
3. Create the view
# views.py
import requests
from django.conf import settings
from django.http import HttpResponse, JsonResponse
def screenshot(request):
target_url = request.GET.get("url", "https://example.com")
payload = {
"url": target_url,
"format": "png",
"fullPage": True,
"viewport": {"width": 1280, "height": 720},
}
try:
response = requests.post(
"https://api.screenshot-api.org/api/v1/screenshot",
headers={
"Authorization": f"Bearer {settings.SCREENSHOT_API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=60,
)
except requests.RequestException as exc:
return JsonResponse({"error": "Screenshot service unavailable", "detail": str(exc)}, status=502)
if not response.ok:
return JsonResponse({"error": response.text}, status=response.status_code)
return HttpResponse(
response.content,
content_type=response.headers.get("Content-Type", "image/png"),
)
This view is an adaptation of the provider’s documented HTTP contract, not a provider-tested Django snippet. The endpoint, bearer header, JSON body, URL, format, full-page flag and viewport fields are the documented concepts; timeout and error handling are application choices.
4. Wire the URL
# urls.py
from django.urls import path
from .views import screenshot
urlpatterns = [
path("screenshot/", screenshot, name="screenshot"),
]
Request /screenshot/ for the default page or /screenshot/?url=https%3A%2F%2Fexample.com for another URL. In production, authenticate this Django endpoint, rate-limit it and allow-list destinations. Accepting arbitrary user-supplied URLs can create a server-side request forgery risk, including access to private network addresses.
GET, POST and capture options
When GET is sufficient
The API documents GET requests for simple query-parameter calls. They are convenient for a single URL and a few basic settings, but query strings become difficult to audit when options grow.
Why POST is usually better in Django
POST sends a structured JSON body and is the documented choice for advanced controls. The required url identifies the page. format accepts PNG, JPEG, WebP or PDF. viewport.width and viewport.height set the browser viewport, while fullPage: true captures content beyond the initial viewport.
Rank #2
payload = {
"url": "https://example.com/pricing",
"format": "webp",
"fullPage": False,
"viewport": {"width": 1440, "height": 900},
}
The reference also lists POST-only controls for custom CSS, JavaScript, hidden selectors, geolocation and PDF-related settings such as paper configuration and output ranges. Consult the provider’s endpoint documentation before relying on a particular field name or value.
PDF responses
Set format to pdf and pass the returned bytes through with the response’s PDF content type. PDF-specific options are available through the documented POST controls; keep the response handling binary rather than decoding it as text.
Batch capture
For multiple pages, use the documented batch endpoint: https://api.screenshot-api.org/api/v1/screenshot/batch. Batch jobs can reduce application-side request orchestration, but validate every URL and decide how partial failures should be represented to your users.
Use the Python SDK or direct HTTP?
The provider’s official package is installed with pip install screenshot-api and is documented as working with Django, Flask and FastAPI. Choose it when its supported methods match your needs and you want dependency-level abstraction. Choose requests (or another HTTP client) when you need transparent control over the endpoint, headers, payload, timeout and error mapping. The available SDK material does not publish a complete Django method signature, so do not copy an invented call pattern; follow the package’s current documentation and inspect its returned response type.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesProduction hardening
- Validate destinations: accept only approved schemes and hosts, resolve DNS safely and block localhost, link-local, loopback and private-address targets unless your architecture explicitly requires them.
- Protect the view: require user authentication where appropriate, apply per-user rate limits and cap the requested page size or frequency.
- Set bounded timeouts: use a connect/read timeout that fits your request budget. Return a controlled 502 or 504 rather than holding a worker indefinitely.
- Preserve content types: use the service’s response header when returning PNG, JPEG, WebP or PDF bytes.
- Control caching: cache captures whose source URL and options are identical; invalidate when the page changes.
- Move slow work off the request path: queue long captures with your task system and store the resulting bytes in object storage, returning a job status to the client.
- Log safely: record status, duration and a normalized host, but never log the bearer key or sensitive query parameters.
Common failures and fixes
401 or 403 response
Check that the environment variable is present in the web process (not only your shell), that the value is current and that the header is exactly Authorization: Bearer YOUR_KEY. Restart the process after changing configuration.
400 validation error
Confirm that url is present and absolute, format is one of PNG, JPEG, WebP or PDF, and viewport values are numbers. For complex options, send JSON with POST instead of encoding nested data into a GET query string.
Timeouts or blank captures
Verify that the target is reachable from the provider, not protected by an interactive login, and that the page finishes loading within your timeout. Try a smaller page or viewport, then inspect the provider’s error body. A Django request timeout does not make the remote page load faster; use background jobs for slow pages.
Image displayed as text or downloaded incorrectly
Return response.content, not response.text, and set the upstream Content-Type. PDFs must be treated as binary data as well.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Unexpected SSRF exposure
Do not pass an unrestricted ?url= parameter to an internet-facing view. Enforce an allow-list or accept an internal object identifier that maps to a known URL.
Django Selenium screenshots for tests
Django’s own browser-testing workflow is the better fit for regression evidence. Its documentation covers SeleniumTestCase, the --screenshots test-runner option, @screenshot_cases(...) and self.take_screenshot("name"). Documented cases include desktop, mobile, small-screen, right-to-left, dark and high-contrast variants.
This captures the local test browser and exercises your application in a test context. A hosted API instead captures a URL through an external service and is suitable when screenshots are an application output. Select based on purpose, not just implementation language.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
ScreenshotNeo is a hosted screenshot API and MCP server. One GET request returns PNG, JPEG, WebP or PDF, and its Django integration needs no Selenium installation:
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteBest Value
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for request options. It removes cookie-consent banners, newsletter popups and chat widgets before capture; bot checks, blank pages, failed loads, timeouts and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Can a browser call the screenshot API directly?
It should not when authentication uses a secret API key. Keep the request in Django and expose only your own controlled endpoint.
Should I return the bytes or save a file?
Return bytes for an immediate download or image response. Save to object storage when captures are reused, large, asynchronous or part of a report pipeline.
Is full-page capture the same as a tall viewport?
No. A viewport sets the browser’s visible dimensions; fullPage asks the service to include content beyond that initial viewport.
Recommended Free Tools
Frequently Asked Questions
Can I authenticate the hosted API with a query-string key?
The documented recommendation is an Authorization bearer header. Follow that method so credentials are less likely to leak through URLs, logs or referrers.
Which method is easier to troubleshoot, GET or POST?
GET is quickest for a URL and basic parameters. POST is easier to inspect and extend because options remain structured JSON.
When should I choose Django Selenium instead?
Choose Selenium when you are testing your own application across documented browser variants; choose a hosted API when capture is a runtime feature or must target an external URL.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

