Website Screenshot & HTML to PDF Generator API
Pricing
from $7.00 / 1,000 screenshots
Website Screenshot & HTML to PDF Generator API
Input: page URLs, or your own HTML. Output: one row per capture with a link to the file — PNG, JPEG, WebP or PDF; full page, viewport, custom size or one CSS-selected element. Banners hidden, ads blocked, lazy images loaded. Device presets, retina, dark mode, locale. Failed URLs are not charged.
Pricing
from $7.00 / 1,000 screenshots
Rating
0.0
(0)
Developer
Power On Labs
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
3
Monthly active users
a day ago
Last modified
Categories
Share
Website Screenshot & PDF Generator API
A website screenshot API that captures any web page as a PNG, JPEG, WebP or PDF — full page, visible viewport, or a single element. Built for the part every other screenshot tool leaves broken: the cookie banner covering the hero image, the lazy images that never loaded, the ad slot that left a grey hole in the middle of your capture.
Give it a list of URLs — or your own HTML, for documents that have no address yet. Get back clean images (or PDFs) and a dataset row per capture with a direct file link — usable from the Apify API, the REST API, or the visual UI, with no server of your own to run or maintain.
What makes this website screenshot API different
Most "URL to image" tools stop at rendering the page and hoping for the best. This one handles the reasons a plain screenshot looks broken:
| Cookie banners removed | Consent overlays from OneTrust, Cookiebot, Didomi, Quantcast, Usercentrics, Sourcepoint, Iubenda and 40+ others are stripped before the capture. The default removes the banner rather than clicking it, so no consent is given and no tracking cookies are set. Switch to "reject all" or "accept all" if you need a real click instead. |
| Ads blocked and their empty slots collapsed | Blocking ad requests alone leaves grey boxes labelled "Advertisement". Those get cleaned up too, so a full-page screenshot doesn't look broken. |
| Lazy-loaded images actually load | The page is scrolled before a full-page capture, so images below the fold render instead of coming back blank. |
| Real device presets | Desktop 1920, laptop 1366, iPad and iPhone viewports with matching user agent, touch support and pixel density — not just a resized browser window. |
| Retina / high-DPI output | 2x and 3x pixel density for crisp images in presentations, decks and documentation. |
| Element screenshots | Give a CSS selector and capture just that element — a pricing table, a chart, a single card — instead of the whole page. |
| Webpage-to-PDF export | Single-page PDF sized to the real page height, or standard A4, as an alternative output to an image. |
| HTML to PDF | Send your own HTML instead of a URL — an invoice, a report, a receipt — and get it back as a PDF or an image, using the same rendering engine. |
| Batch capture in parallel | Many URLs in one run, with automatic retries. One broken URL doesn't kill the run — you get a row explaining what went wrong and the rest complete normally. |
Quick start
Minimal input — just a list of URLs:
{ "urls": ["https://example.com"] }
Call it however fits your stack: the Apify API and REST endpoints, the official Node.js and Python clients, or no-code via Zapier, Make or n8n through Apify's integrations. A minimal call with the JavaScript client:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<APIFY_TOKEN>' });const run = await client.actor('power_on/screenshot-url-pdf').call({urls: ['https://example.com'],device: 'desktop',format: 'png',});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items[0].fileUrl);
And with the Python client:
from apify_client import ApifyClientclient = ApifyClient('<APIFY_TOKEN>')run = client.actor('power_on/screenshot-url-pdf').call(run_input={'urls': ['https://example.com'], 'format': 'pdf'})items = client.dataset(run['defaultDatasetId']).list_items().itemsprint(items[0]['fileUrl'])
HTML to PDF
Instead of a URL, you can send the HTML yourself. It is rendered in the same browser and comes back in the same output formats — useful for invoices, reports, receipts and email templates that exist as markup and have no public address:
{"html": "<h1>Invoice 2026-0042</h1><table>...</table>","format": "pdf","fullPage": false}
fullPage: false gives a standard A4 page, which is what a printable document
usually wants; fullPage: true gives a single page as wide as the viewport and as tall
as the content. Images, CSS and fonts must use absolute URLs (https://…) or data
URIs: inline HTML has no address of its own for relative paths to resolve against. When
html is set, urls is ignored.
Input parameters
Give it either urls or html. Everything else has a sensible default.
{"urls": ["https://example.com","https://news.ycombinator.com"],"device": "desktop","fullPage": true,"format": "png","scaleFactor": 2,"dismissCookieBanners": "hide","blockAds": true}
Useful extras: selector (capture one element), hideSelectors (kill a sticky header
or a chat widget), customCss, darkMode, waitForSelector, delayMs, locale,
timezone, cookies, headers and basicAuthUsername / basicAuthPassword for pages
behind a login, and proxyConfiguration for geo-specific pages. cookies and headers
are stored encrypted and kept out of the run log, so a session token or an
Authorization header is safe to put there. The full list, with descriptions and
defaults, is in the Input tab.
Output
One dataset row per URL:
{"url": "https://example.com","ok": true,"statusCode": 200,"title": "Example Domain","format": "png","width": 1920,"height": 3480,"pageHeight": 3480,"truncated": false,"bytes": 214233,"device": "desktop","scaleFactor": 2,"durationMs": 1842,"key": "001-example.com.png","fileUrl": "https://api.apify.com/v2/key-value-stores/.../records/001-example.com.png"}
width and height describe what is actually in the file, in CSS pixels — the
whole page, the viewport, the A4 sheet, or the element you selected — so the file is
width x height x scaleFactor real pixels. pageHeight is how tall the document was,
and truncated says whether the capture stopped short of it.
The image or PDF is stored in the run's key-value store, and fileUrl is a direct
link to it — no separate download step. Failed URLs come back with ok: false and
the reason in error, instead of stopping the run.
Typical use cases
- Open Graph and social preview images — generate the image your link preview uses when shared on Slack, X or LinkedIn
- Visual monitoring — capture the same pages on a schedule and compare them over time to catch layout regressions or unwanted changes
- Webpage-to-PDF export — archive a page as a PDF with the layout intact, for compliance, records or offline reading
- Design and QA review — desktop, tablet and mobile capture in one run, side by side
- Documentation and changelogs that need current, accurate screenshots without a human taking them by hand
Pricing
Pay per screenshot. A failed URL is not charged. There's no monthly subscription and no minimum commitment — you pay for what you actually capture, unlike most standalone screenshot APIs that charge a fixed monthly plan whether you use it or not.
FAQ
Is there a free website screenshot API? This Actor has no free tier of its own, but every new Apify account starts with free monthly platform credit, which covers a number of screenshots before any charge applies.
Can I take a full-page screenshot, not just the visible area?
Yes — set fullPage: true (the default). The page is scrolled first so lazy-loaded
images below the fold render before the capture.
Can I convert a webpage to PDF instead of an image?
Yes — set format: "pdf". With fullPage: true you get a single-page PDF sized to the
real page height, up to 100,000 pixels; past that the PDF stops there, the run says so
in the log, and the row comes back with truncated: true and the real pageHeight.
With fullPage: false you get standard A4 instead.
Does it handle cookie consent banners automatically? Yes, by default. Overlays from the major consent management platforms are removed before capture, without clicking "accept" — so no consent is granted and no tracking cookie is set. You can switch to a real "accept all" or "reject all" click instead.
Can I screenshot just one element instead of the whole page?
Yes — pass a CSS selector and only that element is captured.
Does this work with pages behind a login?
Yes, via cookies, headers, or basicAuthUsername / basicAuthPassword, depending
on how the site authenticates. All of those are secret input fields: they are stored
encrypted and never printed in the run log.
Known limitations
Worth knowing before you run it:
- On a few sites an ad container also holds real content, and its reserved empty space survives the clean-up. Removing it would risk deleting real content, so it stays.
- Very tall pages: an image is clipped only if the browser engine refuses the capture
outright, and then the row says
truncated: true— in practice captures well past 20,000 pixels come back whole. A full-page PDF is capped at 100,000 pixels, which no ordinary page reaches, and a page past it is reported astruncatedrather than quietly cut. - Pages behind a bot wall may need
proxyConfigurationand a longertimeoutSecs. - Video and animation are captured as a still frame, at whatever moment the page is in.
Related tools
Also from Power On Labs:
- Sitemap URL Extractor —
turns a domain into every page URL it publishes. Its output is already the list
this Actor takes in
urls, so the two chain: sitemap first, capture second, when you want a screenshot of every page rather than of the home page. - Tech Stack Audit — what each of those pages is built with: CMS, framework, CDN, analytics and tracking pixels, with the evidence for every detection.
- PDF to JSON Extractor — the other direction: a PDF back into tables, key fields and Markdown.
Need the page's text or structured data instead of a picture of it? Apify's Website Content Crawler extracts clean text and markdown from a site — a common pairing with this Actor when you need both a visual and the content.
Support
Found a page it handles badly? Open an issue on this Actor with the URL and the settings you used. Broken pages are the fastest way to make it better, and they get fixed.