snaplab Screenshot & PDF Renderer
Pricing
Pay per usage
snaplab Screenshot & PDF Renderer
Render any URL or raw HTML to a PNG/JPEG/WebP screenshot or a PDF, with ad blocking, cookie-banner removal, dark mode and full-page capture.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Harpreet Singh
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Share
Point this actor at a list of URLs (or a blob of raw HTML) and get back clean PNG, JPEG, WebP or PDF files — no ad clutter, no cookie banners, no half-loaded pages. It runs a real headless chromium on the Apify platform, so what you get is what a browser sees, at whatever viewport, colour scheme and page length you ask for. Every render lands in the run's key-value store with a direct link in the dataset row next to it.
What it does
- Renders any URL or raw HTML to PNG, JPEG, WebP or PDF.
- Full-page capture — the whole scrollable document, not just the fold.
- Ad & tracker blocking — requests to known ad, analytics and session-replay hosts are aborted before they load.
- Cookie-banner removal — common consent dialogs are hidden, and an obvious accept button is clicked when one is present.
- Dark mode — emulates
prefers-color-scheme: dark. - Custom viewport — width and height from 320×240 up to 4096×4096.
- Render delay — wait up to 10 seconds after load for animations and lazy-loaded content.
- Files land in the key-value store, with a direct link (
keyValueStoreUrl) in each dataset row.
Input
{"urls": [{ "url": "https://news.ycombinator.com" }, { "url": "https://example.com" }],"mode": "screenshot","format": "png","fullPage": true,"width": 1280,"height": 800,"darkMode": false,"blockAds": true,"blockCookieBanners": true,"delay": 500}
Leave urls empty and pass html instead to render a string of markup. Pass both and you get one render per URL plus one for the HTML.
Output
One dataset row per target:
{"url": "https://news.ycombinator.com","kind": "screenshot","keyValueStoreUrl": "https://api.apify.com/v2/key-value-stores/aBcDeFgHiJkLmNoPq/records/render-0-1757210000000.png","width": 1280,"height": 800,"bytes": 412870,"tookMs": 2841}
The binary file itself is not in the dataset — it lives in the run's key-value store at the keyValueStoreUrl shown in the row. Fetch that URL to download the image or PDF.
A target that fails produces a row with an error field instead of a file, and the run carries on with the next target.
Pricing
This actor is pay per event:
| Event | Price | When |
|---|---|---|
| Actor start | $0.005 | Once, when the run starts |
| Successful render | $0.003 | Per URL or HTML input rendered successfully |
So a run that screenshots 100 URLs costs about $0.305 — $0.005 to start plus 100 × $0.003.
Failed renders are not charged. If a page times out or errors, you get a dataset row with the error message and no charge for it.
Implementation note for maintainers: the event definitions live in two places that must be kept in sync —
.actor/pay_per_event.jsonas a standalone file, and apayPerEvent.actorChargeEventsblock inside.actor/actor.json. Apify has used both conventions; carrying both means the platform finds the pricing whichever key it reads. Change one, change the other.
Also available as a hosted REST API
If you'd rather call an endpoint than run an actor, the same renderer is available as a REST API at snaplab.dev:
curl -X POST https://snaplab.dev/api/render \-H "Authorization: Bearer sk_..." -H "Content-Type: application/json" \-d '{"url":"https://example.com","format":"png","fullPage":true}' -o shot.png
100 free renders a month, plus PDF, HTML→image, signed URLs for <img> tags, an n8n community node, and an MCP server at https://snaplab.dev/mcp so Claude and Cursor can see any page. Docs: snaplab.dev/docs.
FAQ
Can I render pages behind a login? Not in v1. There is no cookie, header or credential input yet, so every page is fetched as an anonymous visitor. Public pages, paywall-free articles and your own marketing pages all work fine.
Why is my full-page screenshot cut off?
Very long pages hit chromium's own capture limits, and many sites only load images as you scroll. Set delay to 1000–3000 ms so lazy-loaded content has time to appear before the capture. If the page is genuinely enormous, capture it as a PDF instead.
Does PDF mode respect width and height?
No. In PDF mode the page size comes from pdfFormat (A4, Letter, Legal, A3, A5) and landscape. The width/height inputs only shape the browser viewport used for screenshots.
What happens if one URL fails?
You get a dataset row containing that URL and an error message, the run continues to the next target, and you are not charged the render event for it.
Can I get JPEG at a specific quality?
Not in v1 — JPEG quality is fixed at 80, which is a good size/fidelity trade-off for page captures. Use png or webp if you need lossless or smaller lossless-ish output.
How do I get the file?
Every dataset row carries a keyValueStoreUrl. That URL points at the record in the run's key-value store; fetch it to download the PNG, JPEG, WebP or PDF.
Does this actor call the snaplab API? No. It is self-contained: it launches its own Playwright chromium on the Apify platform, so an Apify run needs no snaplab account or key. The hosted API above is the same capability behind a REST endpoint, for when you want to call it from your own code.
Changelog
0.1
- Initial release: URL and raw-HTML rendering, screenshot (PNG/JPEG/WebP) and PDF modes, full-page capture, ad and tracker blocking, cookie-banner removal, dark mode, custom viewport, render delay, pay-per-event pricing.