October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk7 min

How to Create a Website Screenshot API for Testing an Application

A practical guide to building a browser-backed screenshot endpoint with Python and Playwright, returning image artifacts, and using them reliably in visual regression tests.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Build a small API that accepts a URL and capture settings, renders the page in a browser worker, and returns a screenshot. Keep that capture service separate from visual regression testing: the API produces an image artifact; your test runner compares it with an approved baseline. Below is a minimal Python implementation using FastAPI and Playwright, followed by the design choices and failure cases to address before using it in a test pipeline.

What the screenshot API should do

A screenshot API is a browser-automation service with a narrow HTTP contract. A caller submits a target URL and capture options; the service navigates to the page, captures its rendered state, and returns image bytes. Playwright’s Page API supports navigating to a URL and capturing a screenshot to a file, and its screenshot operation can also return a buffer for an API to return, encode, upload, or post-process.

Start with a small request surface: a URL, viewport dimensions, an optional full-page flag, an image format, and a bounded navigation timeout. Add authentication or other controls only when your test environment needs them. This is a practical design recommendation, not a standard request schema.

Build a minimal Python screenshot endpoint

This example uses FastAPI for the HTTP layer and Playwright’s asynchronous Python API for browser work. Install FastAPI, Uvicorn, and Playwright, then install Playwright’s Chromium browser before starting the service:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
FORA Pro Voice V9 Diabetes Testing Kit for Accurate and Easy Monitoring Your Blood Glucose with Talking Glucometer, 1 Meter, 100 Test Strips, 100 Lancets, 1 Painless Design Lancing Device, Carry Case
  • Audible test results with 2 languages: English & Español
  • Less Pain with Alternative Site Testing
  • No extra coding needed for the meter
  • Available for storing 450 test memories with date & time
  • User-friendly interface: quick to show you all test results and related information
python -m pip install fastapi uvicorn playwright
python -m playwright install chromium

Save the following as app.py. It accepts a URL and bounded capture settings, creates an isolated browser context for each request, and returns the PNG bytes directly.

from typing import Literal
from urllib.parse import urlparse

from fastapi import FastAPI, HTTPException
from fastapi.responses import Response
from pydantic import BaseModel, Field
from playwright.async_api import async_playwright, TimeoutError as PlaywrightTimeoutError

app = FastAPI()


class ScreenshotRequest(BaseModel):
    url: str
    width: int = Field(default=1440, ge=320, le=3840)
    height: int = Field(default=900, ge=240, le=2160)
    full_page: bool = False
    format: Literal["png", "jpeg"] = "png"
    timeout_ms: int = Field(default=30000, ge=1000, le=60000)


@app.post("/screenshot")
async def screenshot(request: ScreenshotRequest) -> Response:
    parsed = urlparse(request.url)
    if parsed.scheme not in {"http", "https"} or not parsed.netloc:
        raise HTTPException(status_code=400, detail="url must be an absolute http or https URL")

    try:
        async with async_playwright() as playwright:
            browser = await playwright.chromium.launch()
            try:
                context = await browser.new_context(
                    viewport={"width": request.width, "height": request.height}
                )
                try:
                    page = await context.new_page()
                    await page.goto(
                        request.url,
                        wait_until="networkidle",
                        timeout=request.timeout_ms,
                    )
                    image = await page.screenshot(
                        type=request.format,
                        full_page=request.full_page,
                    )
                finally:
                    await context.close()
            finally:
                await browser.close()
    except PlaywrightTimeoutError:
        raise HTTPException(status_code=504, detail="page navigation timed out")
    except Exception as exc:
        raise HTTPException(status_code=502, detail=f"browser capture failed: {exc}")

    media_type = "image/png" if request.format == "png" else "image/jpeg"
    return Response(content=image, media_type=media_type)

Run it locally with uvicorn app:app --host 127.0.0.1 --port 8000. Send a request with curl -X POST http://127.0.0.1:8000/screenshot -H 'Content-Type: application/json' -d '{"url":"https://example.com","width":1440,"height":900,"full_page":false,"format":"png"}' --output page.png. A successful request returns the image itself, so save the response body as a file rather than trying to parse it as JSON.

Important production boundary

This is a minimal example, not a hardened public service. Accepting arbitrary URLs can expose infrastructure or internal network resources if the endpoint is reachable by untrusted callers. Before exposing it, determine and implement the URL, network, browser-sandbox, authentication, quota, privacy, and retention controls appropriate to your environment. Those controls are deployment-specific; the example does not establish a complete security policy.

Rank #2
KeeYees USB Logic Analyzer Device with 12PCS 6 Colors Test Hook Clip Set USB Cable 24MHz 8CH 8 Channel UART IIC SPI Debug for Arduino FPGA M100 SCM
  • This kit contains 12pcs SMD IC 6 Colors Test Hook Clips which are ideal for using this 24MHz 8CH logic analyzer.
  • If you are doing microcontroller, ARM system, FPGA development, we highly recommend you purchase this product! This item will help you solve your problem when you do MCU related products, especially for UART, SPI, IIC and other communication debugging.
  • Compatible with the Logic analysis software and open source programs such. B. sigrok (protocol analysis of RS232, SPI, IIC, 1-Wire, etc.)
  • Reliable Technical Support: We have prepared detailed tutorial, includes: guidance manual, demo code, burning tools, necessary class libraries. Please visit our website (github: Keeyees/KY-57) to get tutorial or can contact us on Amazon, we will send PDF Document to you.

Choose how captures move through the service

Return image bytes for short captures

A synchronous image response is straightforward for small, bounded test captures: the caller submits a request and receives PNG or JPEG bytes. Playwright’s screenshot operation returns a buffer, so the service can return it without first writing a local file. The Page API also supports saving a screenshot to a path if your workflow needs a local artifact.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a job and artifact reference for longer work

For captures that may take longer or produce large full-page images, an asynchronous design can return a job identifier and let the client retrieve the finished artifact separately. That adds job state and artifact retrieval to the service, but avoids requiring one request to remain open for the entire browser operation. This is an architectural trade-off, not a measured performance claim.

Keep browser work behind a worker boundary

For a service that handles concurrent test requests, separate request validation from browser execution. A handler can validate and submit a bounded job; a worker can launch or reuse a managed browser, create an isolated context and page, navigate, capture, and return the buffer or store the artifact. Close the page and context and release browser resources when the job finishes. This architecture is an engineering pattern, not a benchmarked implementation.

Rank #3
Website Testing Software Developer Website Tester Graphic Laptop Sleeve
  • Website Testing Software Developer Website Tester. This Quality Assurance: My Superpower is for men and women into website testing. Great for a website tester who test and evaluate websites or web applications.
  • Are you a software developer in programming? Are you a web tester who ensure websites functionality? Then this website testing design is for you. Ideal website tester apparel for a computer programmer.
  • Lightweight, form-fitting laptop sleeve that protects your laptop from daily wear and tear
  • Faux fur-lined interior and padded zipper binding prevent scratches while keeping your device secure with a top-loading zippered enclosure and two sliders
  • Designed for on-the-go use with a slim profile that easily slides into backpacks, totes, and carry-on bags

Make screenshots useful for visual regression tests

Capturing a screenshot does not by itself decide whether the page changed incorrectly. A visual regression test needs a reference image and controlled capture conditions. Differences in host operating system, browser version, browser settings, hardware, power source, or headless mode can alter rendered pixels. Keep the baseline and new capture environment consistent: use the same browser and version, operating system, viewport, fonts, and rendering mode.

Use Playwright Test when you want built-in comparison

Playwright Test provides the toHaveScreenshot() assertion for comparing page screenshots with expected snapshots. Playwright’s PageAssertions documentation says the assertion “will wait until two consecutive page screenshots yield the same result, and then compare the last screenshot with the expectation.” The assertion belongs to the Playwright test runner; it is not a feature of a generic screenshot endpoint.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The assertion also has controls for masks, caret behavior, clipping, and pixel differences, and can disable animations by default. For dynamic regions such as timestamps, rotating content, or personal data, use a mask or test stylesheet deliberately. Record those adjustments in the test so the comparison still checks the intended page state.

Use the capture API with another test runner

A standalone screenshot service can return image artifacts for tests written in other frameworks. Your runner remains responsible for choosing the baseline, comparing pixels, deciding what difference is acceptable, and reporting the result. Keep the capture endpoint interoperable rather than tying it to one assertion library.

Preserve failure evidence

When a comparison fails, retain enough context to reproduce it: the test name, URL, browser project, viewport, baseline reference, actual screenshot, and diff artifact where available. Review baseline updates before committing them; automatically accepting every new image can turn a real regression into the new expected result.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Choose viewport or full-page capture

A viewport screenshot captures the visible browser area at the selected dimensions. It is usually the more bounded artifact for checking a particular screen state. Full-page capture includes the scrollable page and is useful when the test needs to inspect content beyond the initial viewport; Playwright supports this option. Long pages can produce much larger images, so choose it when the additional page coverage answers a test requirement.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
14 Routine Urine Analyzer - USB Rechargeable, 4-inch Color Screen, Biochemistry Testing Device for Home, Hospital & Clinics - Accurate Urinalysis Tool
  • 【Detection Principle】: Utilizes High Brightness Cold Light Source Reflection Measurement Technology for Accurate Results
  • 【Test Speed】: Conducts Single-Step Tests at 60 TestsHour and Continuous Tests at 120 TestsHour for Efficient Water Quality Assessment
  • 【Database Capacity】: Stores Up to 1 Million Test Results, Ensuring Comprehensive Data Management for Various Water Quality Testing Needs
  • 【Test Environment】: Operates Effectively in Conditions Ranging from 18℃ to 25℃ with Humidity Levels Below 80% for Reliable Readings
  • 【Usage Scenarios】: Ideal for Water Quality Testing in Swimming Pools, Sea Water, Ponds, Sewage, Industrial Water, and Water Applications

Troubleshoot common capture failures

  • 400 response for the URL: The request must contain an absolute HTTP or HTTPS URL. Check for a missing scheme or malformed address.
  • 504 navigation timeout: The page did not complete the selected navigation wait within the configured limit. Check whether the site is reachable from the worker, whether the timeout is too short for that test, and whether waiting for networkidle is appropriate for a page with continuing network activity.
  • 502 browser capture failure: The browser could not complete navigation or capture. Inspect the service logs and browser installation, and verify that the target is accessible from the worker.
  • Image differs across runs: Stabilize browser version, host environment, viewport, fonts, rendering mode, and page state. Mask or style known dynamic content explicitly rather than accepting unexplained pixel differences.
  • Image is unexpectedly large: Check whether full-page capture was requested and whether the page is unusually long. Use viewport capture when the test only concerns the visible region.
  • Client cannot decode the response: The endpoint returns raw image bytes with an image content type, not a JSON object. Save or pass the response body to an image-aware client.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. A single GET request can return PNG, JPEG, WebP, or PDF; for a basic capture:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

See the ScreenshotNeo API documentation for the request options. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status. Its MCP server exposes screenshot, page-info, and PDF-capture tools for AI agents. The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots.

Sign up for ScreenshotNeo’s free plan to try up to 1,000 screenshots a month with no card.

Frequently Asked Questions

Can a screenshot endpoint perform visual regression testing by itself?

No. It returns the capture artifact; a test runner or comparison step must compare that image with a reference and decide whether the difference passes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do I need Playwright Test to use Playwright screenshots?

No. The browser capture APIs can be used independently. The built-in toHaveScreenshot() assertion, specifically, is available only with the Playwright test runner.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Shenzhen desk3 min
    HONOR Expands Beyond Smartphones With Humanoid Robot RevealHONOR said it unveiled its first humanoid robot at MWC 2026 and named shopping assistance, workplace inspections, and supportive companionship as intended uses. Later Robotics D1 claims and a reported…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.