PageSnapper is a lightweight website screenshot API built with ASP.NET Core and Playwright.
It captures high-quality screenshots of public websites and returns them as PNG images.
Features include desktop/mobile rendering, full-page capture, optional cookie-consent cleanup, API key authentication, caller allowlists and SSRF protection.
The project was originally extracted from a larger production system and turned into a standalone service.
A public demo instance is available:
https://pagesnapper-demo.mevisto.se/swagger
The demo instance is rate limited and intended for testing only.
Example screenshot generated by PageSnapper:
- PNG website screenshots
- Desktop and mobile rendering
- Viewport or full-page capture
- Optional cookie consent cleanup (
clean=true) - API key authentication
- Caller allowlist using
Origin/Referer - SSRF protection for localhost/private networks
- Basic in-memory rate limiting
- Retry logic for unstable pages
- Swagger API documentation
/healthendpoint- CLI client for quick screenshot capture
GET /api/screenshot
| Parameter | Required | Description |
|---|---|---|
| url | yes | Target URL |
| mode | no | desktop or mobile |
| capture | no | viewport or fullpage |
| clean | no | true attempts to remove cookie banners |
curl "https://localhost:5001/api/screenshot?url=https://example.com&mode=desktop&capture=viewport&clean=true" --output screenshot.png
With API key:
curl -H "X-Api-Key: your-api-key" "https://localhost:5001/api/screenshot?url=https://example.com" --output screenshot.png
A small CLI tool is included for quickly capturing screenshots from the command line.
Example:
dotnet run --project src/PageSnapper.Cli --url https://example.com --mode desktop --output shot.png
Options:
| Option | Description |
|---|---|
| --url | Target website |
| --mode | desktop or mobile |
| --capture | viewport or fullpage |
| --clean | enable cookie banner cleanup |
| --output | output filename |
Client │ │ HTTP request ▼ PageSnapper API │ │ validates request │ (API key / caller allowlist) ▼ URL validation (SSRF protection) │ ▼ Playwright browser │ │ renders page │ optionally removes cookie banners ▼ PNG screenshot │ ▼ Returned to client
dotnet restore dotnet build dotnet run
Open Swagger:
https://localhost:5001/swagger
Health check:
After restoring the project you must install Chromium once:
playwright install chromium
If that command is not available:
dotnet tool install --global Microsoft.Playwright.CLI playwright install
- Publish the API project
dotnet publish src/PageSnapper.Api/PageSnapper.Api.csproj -c Release -o .\publish\PageSnapper.Api
- Create an IIS site pointing to the published folder
- Use an Application Pool with No Managed Code
- Install the ASP.NET Core Hosting Bundle on the server
- Install Playwright browsers on the server
- Configure appsettings.json
- Verify /swagger and /health
{ "ScreenshotSecurity": { "Enabled": true, "ApiKeyHeaderName": "X-Api-Key", "ApiKeys": [ { "Name": "prod", "Key": "replace-this", "Scopes": [ "png" ] } ], "AllowedCallers": [ "localhost", "*.example.com" ], "RequestsPerMinute": 60 } }
A request is allowed when one of the following is true:
- A valid API key is provided
- The caller host is present in AllowedCallers
Caller hosts are validated using the Origin and Referer headers.
The target URL is validated to block:
- localhost
- loopback
- private network ranges
- link-local addresses
This prevents common SSRF attack vectors.
- Full-page screenshots can be large and slower than viewport screenshots.
- clean=true improves many pages but cannot guarantee perfect cookie-banner removal on all sites.
- Some modern websites can be unstable in headless browsers; retry logic is included.
- Caller allowlists typically apply to requests made from web pages, not direct navigation in the browser.
MIT License
