Turn any invoice or web page into a pixel-perfect PDF.

snapframe renders any URL to PDF, screenshot, or social preview image with one API call. Built for developers who need "Export to PDF" without running a browser farm. Paid plans, manual provisioning, no credit card needed.

Try it right now

Paste any public URL. We'll render a real screenshot or PDF, live, no signup.

Live render result

Free demo: 5 renders/hour per visitor. Full API keys get much higher limits.

Invoice → PDF, end to end

This demo ran on the live API. An invoice page goes in, a print-ready A4 PDF comes out in seconds.

1

The invoice page

A normal HTML invoice — the kind your app already renders for customers.

2

One API call

Your backend POSTs the page URL. Add ?sync=true to get the file back in the same call — no polling.

3

The PDF

A finished PDF, ready to email or offer as a download. One render = one quota unit.

Invoice HTML page

Integrate in minutes

Your API key goes in the X-API-Key header. Full interactive reference: api.snapframe.mooo.com/docs (OpenAPI).

cURL
curl -X POST "https://api.snapframe.mooo.com/v1/pdf?sync=true" \
  -H "X-API-Key: snap_your_key" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://yourapp.com/invoices/2041","format":"A4"}' \
  -o invoice.pdf
Python
import requests
API, H = "https://api.snapframe.mooo.com", {"X-API-Key": "snap_your_key"}

pdf = requests.post(API + "/v1/pdf?sync=true", headers=H,
    json={"url": "https://yourapp.com/invoices/2041"}).content
open("invoice.pdf", "wb").write(pdf)
JavaScript (Node.js 18+)
const API = "https://api.snapframe.mooo.com";
const H = { "X-API-Key": "snap_your_key", "Content-Type": "application/json" };

const pdf = await fetch(API + "/v1/pdf?sync=true", {
  method: "POST", headers: H,
  body: JSON.stringify({ url: "https://yourapp.com/invoices/2041", format: "A4" })
}).then(r => r.arrayBuffer());
Parameters
EndpointKey parameters
POST /v1/pdfurl or html (one required, max 500KB) · format: A4 / Letter · landscape · print_background · margin_top/bottom/left/right ("1cm") · display_header_footer + header_template/footer_template · wait_ms (0–15000) · ?sync=true
POST /v1/screenshoturl or html (one required, max 500KB) · width 320–3840 · height 240–2160 · full_page · format: png / jpeg · dark_mode · wait_ms · ?sync=true
POST /v1/og-imageurl (required) · fixed 1200×630 viewport · ?sync=true
GET /v1/jobs/{id}status: queued → processing → done / failed
GET /v1/results/{id}Downloads the file. Results kept 14 days.
GET /v1/usageReturns plan, quota_monthly, used_this_month.
All render endpointsheaders (custom request headers) · cookies (for authenticated pages) · webhook_url (POSTed on async completion) · GET /v1/status (public uptime + queue depth)
Errors
CodeMeaning
400Bad URL (also: SSRF-blocked private/internal address).
401Missing or unknown API key.
403Key is paused/disabled.
422Invalid parameters (see the parameter table).
429Monthly quota exceeded — or 60 requests/minute per key.
503Render queue temporarily unavailable — retry.
Security

Simple pricing

One render = one screenshot, PDF, or OG image. Polling, downloads, and usage checks are free.

Standard

$14/mo
  • 1,000 renders / month
  • All endpoints + sync mode
  • Email support
Request access

Pro

$49/mo
  • 10,000 renders / month
  • All endpoints + sync mode
  • Priority support
Request access

Enterprise

Custom
  • Custom volume
  • Dedicated capacity
  • SLA & onboarding
Contact us

Plans are provisioned manually after payment — request access and we'll confirm your plan within a day.

Questions

How do I get an API key?

Email us and after payment is confirmed you receive an API key with your monthly quota — usually within a day.

What counts toward my quota?

Only finished renders: one screenshot, PDF, or OG image = one render. Polling job status, downloading results, and checking usage are free.

What happens if I hit my limit?

New renders pause with a clear "monthly quota exceeded" message until your quota resets next month (or you upgrade). Your files and stats stay available.

Can I render private pages?

Two ways: give a publicly reachable URL (a signed URL works for semi-private content), or send your HTML directly in the html field — nothing is fetched, so login-walled content renders fine. External images/fonts inside your HTML must use absolute URLs.

Do you store my pages?

Render results are kept for 14 days so you can download them, then automatically deleted.