How to Build a Self-Hosted Screenshot API with Docker
Deploy in minutes. No API key. No rate limits.
Why self-host a screenshot API?
Most screenshot services charge per request. At low volumes this is fine. But as soon as you add CI visual regression tests, automated report generation, or an AI agent that needs to observe web pages, the bill grows fast.
A self-hosted screenshot API solves three problems at once:
- Cost — you pay for the server, not per screenshot
- Privacy — URLs and rendered content never leave your infrastructure
- Latency — the service runs on your network, close to your callers
Prerequisites
- Docker and Docker Compose installed (
docker compose version) - Any server or laptop — 1 vCPU and 512 MB RAM is enough for light use
curlto test the API
Step 1: Clone and start
git clone https://github.com/scnix-git/openkova
cd openkova
docker compose upDocker pulls the pre-built image, starts the container, and exposes port 3000. The first start takes 30–60 seconds while Chromium initialises. You should see:
▲ Next.js ready on http://0.0.0.0:3000Step 2: Test with a URL
Open a second terminal and send your first screenshot request. The -N flag keeps the connection open to read the SSE stream:
curl -N -X POST http://localhost:3000/api/convert/url \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "depth": 1}'You'll receive Server-Sent Events with progress updates, then a final data: {"type":"done","filePath":"/data/..."} event. The PNG is saved to the container's /data directory.
Step 3: Convert an HTML snippet
For report generation or OG images, send raw HTML directly — no URL required:
curl -N -X POST http://localhost:3000/api/convert/snippet \
-H "Content-Type: application/json" \
-d '{
"html": "<div style=\"background:#7c6af7;color:white;padding:48px;font-family:sans-serif;font-size:2rem\">Hello, Openkova</div>"
}'Step 4: Upload an HTML file
If your template lives on disk, use the multipart upload endpoint:
curl -N -X POST http://localhost:3000/api/convert/file \
-F "file=@./invoice.html"API reference summary
| Endpoint | Content-Type | Body |
|---|---|---|
POST /api/convert/url | application/json | {"url":"...","depth":1} |
POST /api/convert/snippet | application/json | {"html":"...} |
POST /api/convert/file | multipart/form-data | file=@path/to/file.html |
All three endpoints return an SSE stream. See the API reference for the full event format.
Deploying to a VPS or cloud platform
To deploy outside your laptop, copy the docker-compose.yml to your server and run docker compose up -d. Set these environment variables in your platform dashboard or a .env file:
CHROMIUM_PATH=/usr/bin/chromium
OPENKOVA_STORAGE_PATH=/dataOn Railway, Render, or Fly.io, the Dockerfile handles Chromium installation automatically — just point to the repository and deploy. Railway with a Dockerfile builder works reliably because Chromium installs from Debian apt (not snap).
Production considerations
- Authentication — Openkova has no built-in auth. Put it behind a reverse proxy (Nginx, Caddy, Traefik) and add an API key header check, or restrict access to your internal network only.
- Concurrency — each screenshot launches a Chromium tab. Under high load, add a queue or set resource limits per container.
- Storage — PNG files accumulate in
OPENKOVA_STORAGE_PATH. Mount a volume and add a cron job to prune old files. - Memory — allocate at least 512 MB RAM; 1 GB is comfortable for concurrent requests.
Frequently asked questions
What is a self-hosted screenshot API?
A web service you run on your own infrastructure — on a VPS, Docker host, or cloud container — that converts HTML or URLs to PNG. No SaaS account, no API key, traffic stays on your servers.
Does Openkova require an API key?
No. It is MIT-licensed open-source software. There are no usage fees, no rate limits, and no registration required.
How does Openkova handle Chromium in Docker?
The Docker image uses node:24-slim (Debian) and installs Chromium via apt-get. This gives a real binary at /usr/bin/chromium. The CHROMIUM_PATH env var tells Openkova where to find it.
Can I deploy Openkova to Railway, Fly.io, or Render?
Yes. Any platform supporting Docker deployment works. Set CHROMIUM_PATH=/usr/bin/chromium and OPENKOVA_STORAGE_PATH to a writable path. The Dockerfile installs Chromium from apt automatically.
Compare Openkova with Urlbox, html2canvas, and wkhtmltopdf, or read about using it as a screenshot API for AI agents.