Website Screenshot API (Apify Actor)
Turn URLs into full-page PDFs or PNG/JPEG screenshots: $0.004 per PDF, $0.0008 per screenshot, failed pages free. Paste URLs or HTML, get downloadable files back. Cookie banners removed, lazy-load scrolling, no API key. Runs as an Apify Actor, callable from MCP clients via the Apify MCP server (https://mcp.apify.com/?actors=pennydata/shot-pdf).
Hosted MCP Server
npx add-mcp 'https://mcp.apify.com/?actors=pennydata/shot-pdf'Installs into Claude Code, Codex, Cursor and more
Documentation
Website Screenshot & URL to PDF Converter, from $0.0008/page (pennydata/shot-pdf) Actor
Website screenshot and URL to PDF in bulk: paste URLs or HTML, get full-page PNG, JPEG or PDF files. $0.0008 per screenshot, $0.004 per PDF, failed pages free. Click Start: the 2 prefilled URLs run as screenshots for under $0.002. No API key.
- URL: https://apify.com/pennydata/shot-pdf.md
- Developed by: Penny Data (community)
- Categories: Developer tools, Automation, Agents
- Stats: 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- User rating: No ratings yet
Pricing
Pay per event
This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events. Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.
Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event
What's an Apify Actor?
An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes. In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours, and optionally produces a well-defined JSON output, datasets with results, or files in key-value store. In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.
How to integrate an Actor?
If asked about integration, you help developers integrate Actors into their projects. You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.
For examples already wired to this Actor's own input schema, see the API section below.
Each client library has reference documentation the quickstart does not restate: JavaScript/TypeScript (npm install apify-client) and Python (pip install apify-client).
README
Website Screenshot & URL to PDF Converter: $0.0008 per page
Give it URLs or HTML and get a full-page screenshot (PNG/JPEG, $0.0008) or PDF ($0.004) per page, rendered in headless Chromium. Failed pages are never charged. Price per page: screenshot $0.0008, PDF $0.004, both $0.0048.
Click Start: the prefilled 2 URLs (example.com and a Wikipedia page) run as is as screenshots (mode: screenshot) and cost at most $0.0016. Want a PDF? Set Output to pdf ($0.004 per page). Each URL returns one row:
| input | httpStatus | title | pdfBytes |
|---|---|---|---|
| https://example.com | 200 | Example Domain | 91,727 |
| https://en.wikipedia.org/wiki/Web_scraping | 200 | Web scraping - Wikipedia | 2,556,322 |
(Real rows from our test runs, 2026-10-16 to 10-21; pdfUrl and screenshotUrl link to the saved files.)
Quick start (only urls is required)
{ "urls": [{ "url": "https://en.wikipedia.org/wiki/Web_scraping" }], "mode": "pdf" }
urls accepts plain strings or {"url": "..."} objects. Every other field has a default.
Why use it
- PDF as well as images:
modeisscreenshot,pdforboth(paper size A4/Letter/Legal/A3, landscape, backgrounds). - HTML to PDF / image: render inline HTML strings (
htmlDocuments), not just URLs. - Full page, viewport or crop:
fullPageon (default) captures the whole page; off captures theviewportWidthxviewportHeightwindow;clipWidth/clipHeightcrop from the top-left corner. - Element screenshot:
screenshotSelectorcaptures only the first element matching a CSS selector. No match gives an error row that is not charged. - Sticky headers:
hideFixedElements(default off) turns fixed elements into absolute and sticky ones into static, so headers, cookie bars and chat widgets do not repeat down a full-page capture. - No charge on failure: each page is charged only after its file is saved; failed pages get an
errorrow and no charge. - Bulk with rate limits: many URLs per run, default concurrency 3, max 60 page loads/minute, automatic retries.
Captura de pantalla web, Website Screenshot, Screenshot erstellen - Español, Deutsch, Português
Español: captura de pantalla de una página web a PNG o PDF (masivo)
Convierte una lista de URL públicas (o tu propio HTML) en capturas de pantalla de página completa (PNG/JPEG) o en PDF, con Chromium sin interfaz. Entrada de ejemplo: { "urls": [{ "url": "https://example.com" }], "mode": "pdf" }. Coste en el plan gratuito: $0,0008 por captura y $0,004 por PDF (1.000 PDF = $4,00); las páginas que fallan no se cobran.
Deutsch: Screenshot von Webseiten erstellen, URL in PDF umwandeln (Liste)
Macht aus einer Liste öffentlicher URLs (oder eigenem HTML) ganzseitige Screenshots (PNG/JPEG) oder PDFs, gerendert mit headless Chromium. Beispiel-Eingabe: { "urls": [{ "url": "https://example.com" }], "mode": "both" }. Kosten im kostenlosen Plan: $0,0008 pro Screenshot und $0,004 pro PDF (Modus both = $0,0048 pro Seite); fehlgeschlagene Seiten werden nicht berechnet.
Português: captura de tela de site e URL para PDF em massa
Transforma uma lista de URLs públicas (ou HTML próprio) em capturas de tela de página inteira (PNG/JPEG) ou PDF, com Chromium headless. Exemplo de entrada: { "urls": [{ "url": "https://example.com" }], "mode": "screenshot" }. Custo no plano gratuito: US$ 0,0008 por captura e US$ 0,004 por PDF (1.000 PDFs = US$ 4,00); páginas que falham não são cobradas.
Example output
One item from a run with mode: both on https://example.com. On the Apify platform screenshotUrl and pdfUrl are links to files in the run's key-value store.
{
"input": "https://example.com",
"finalUrl": "https://example.com/",
"httpStatus": 200,
"title": "Example Domain",
"screenshotUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/screenshot-1.png",
"pdfUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/pdf-1.pdf",
"screenshotBytes": 84613,
"pdfBytes": 91727,
"capturedAt": "2026-10-21T03:22:04.280Z"
}
Failed items get a row with input, error and capturedAt, and are not charged.
Options
Screenshot / PDF / both, full-page, PNG or JPEG, viewport size, clipWidth / clipHeight crop, screenshotSelector element capture, hideFixedElements, scroll to top, wait-until (load, domcontentloaded, networkidle), extra delay, wait for a CSS selector, PDF paper size, landscape, print backgrounds, concurrency and retries. Navigation timeout is 45 s. Colour emoji and fonts render as glyphs (Noto Color Emoji is in the image).
Screenshot FAQ
Screenshot above the fold / only the top of a page? Set fullPage to false for exactly the browser window, or crop a full-page capture with clipHeight:
{ "urls": [{ "url": "https://example.com" }], "fullPage": false, "viewportWidth": 1280, "viewportHeight": 720 }
{ "urls": [{ "url": "https://en.wikipedia.org/wiki/Web_scraping" }], "fullPage": true, "clipHeight": 1500 }
Capture one element?
{ "urls": [{ "url": "https://example.com" }], "screenshotSelector": "p" }
Sticky header repeated down a full-page shot? Turn on hideFixedElements:
{ "urls": [{ "url": "https://en.wikipedia.org/wiki/Web_scraping" }], "fullPage": true, "hideFixedElements": true }
Loading screen captured instead of the loaded page? Wait for the network and for an element that only exists once the page is ready:
{ "urls": [{ "url": "https://example.com" }], "waitUntil": "networkidle", "waitForSelector": "#app .loaded", "delayMs": 3000 }
Am I charged for pages that fail? No. Pages that return HTTP 4xx/5xx, time out or cannot be saved get an error row and no charge. Each result is charged only after the file is saved.
Call it synchronously and get the rows back in one request:
curl -X POST "https://api.apify.com/v2/acts/pennydata~shot-pdf/run-sync-get-dataset-items?token=$APIFY_TOKEN" -H "Content-Type: application/json" -d '{"urls":[{"url":"https://example.com"}],"mode":"pdf"}'
Does it capture pages behind a login? No. It does not log in, inject cookies, solve captchas or rotate proxies. Public pages only.
Can I convert my own HTML to PDF? Yes, pass HTML strings in htmlDocuments and set mode to pdf.
Pricing (pay per event)
Charged only for successful captures, via Actor.charge:
| Event | Price |
|---|---|
screenshot | $0.0008 ($0.80 per 1,000) |
pdf | $0.004 ($4 per 1,000) |
mode both | $0.0048 per page (one screenshot + one PDF) |
Pages answering HTTP 4xx/5xx, timeouts and rejected URLs are not charged. Paid Apify plans get lower tiers. Platform events such as actor start follow Apify's standard pay-per-event rules.
Limits and honesty notes
- No login, no cookie injection, no captcha solving, no proxy rotation to bypass blocks. Pages behind logins, bot walls or captchas may fail or capture the block page.
- Only public
http(s)URLs: localhost, private IP ranges andfile:URLs are rejected. - You are responsible for having the right to capture the pages you submit.
- Not a scraper: it returns images/PDFs, not structured page data.
Run locally
npm install
mkdir -p storage/key_value_stores/default
echo '{"urls":[{"url":"https://example.com"}],"mode":"both"}' > storage/key_value_stores/default/INPUT.json
npm start # or: apify run
## results: storage/datasets/default, files: storage/key_value_stores/default
Use cases
- Archive evidence of how a page looked on a given date (compliance, legal, support).
- Generate PDFs from HTML you supply, such as reports or receipts.
- Create above-the-fold preview images (
clipHeight) for link directories or CMS thumbnails. - Take snapshots of a list of staging pages for visual review.
- Archive competitor sale pages to PDF every day: save the input as an Apify Task and add a daily Schedule; each row has a
capturedAttimestamp. Some retailers block automated browsers, so check each row for anerror.
Built with AI assistance (Claude).
Actor input Schema
urls (type: array):
Public http(s) pages to capture. Each item is a URL string or an object like {"url": "https://example.com"}.
htmlDocuments (type: array):
Optional inline HTML strings to render (HTML to PDF/screenshot).
mode (type: string):
What to produce for each page.
format (type: string):
Image format for screenshots: png (lossless) or jpeg (smaller).
fullPage (type: boolean):
Capture the whole scrollable page instead of only the visible viewport.
viewportWidth (type: integer):
Browser viewport width in pixels.
viewportHeight (type: integer):
Browser viewport height in pixels.
clipWidth (type: integer):
Optional: crop the screenshot to the top-left N px wide. 0 = no crop.
clipHeight (type: integer):
Optional: capture only the top N px of the page (works with full-page on). 0 = no crop.
hideFixedElements (type: boolean):
Unsticks sticky navbars, cookie bars and chat widgets (fixed becomes absolute, sticky becomes static) so they do not repeat or cover content.
screenshotSelector (type: string):
Optional: capture only the first element matching this CSS selector (for example #chart or article). No match gives an unbilled error row. Screenshot mode only.
scrollToTop (type: boolean):
Scroll to the top of the page before capturing.
waitUntil (type: string):
Page lifecycle event to wait for before capturing: load, domcontentloaded or networkidle.
delayMs (type: integer):
Extra time to wait after the page is ready, in milliseconds, before capturing.
waitForSelector (type: string):
Optional selector to wait for (max 15s) before capture.
pdfFormat (type: string):
Paper size used for PDF output.
pdfLandscape (type: boolean):
Render PDFs in landscape orientation.
pdfPrintBackground (type: boolean):
Include CSS background colors and images in PDFs.
maxConcurrency (type: integer):
Maximum number of pages captured in parallel.
maxRetries (type: integer):
How many times to retry a page that fails before reporting an error.
Actor input object example
{
"urls": [
{
"url": "https://example.com"
},
{
"url": "https://en.wikipedia.org/wiki/Web_scraping"
}
],
"mode": "screenshot",
"format": "png",
"fullPage": true,
"viewportWidth": 1280,
"viewportHeight": 800,
"clipWidth": 0,
"clipHeight": 0,
"hideFixedElements": false,
"scrollToTop": true,
"waitUntil": "load",
"delayMs": 500,
"pdfFormat": "A4",
"pdfLandscape": false,
"pdfPrintBackground": true,
"maxConcurrency": 3,
"maxRetries": 3
}
Actor output Schema
results (type: string):
No description
API
You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.
JavaScript example
import { ApifyClient } from 'apify-client';
// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
token: '<YOUR_API_TOKEN>',
});
// Prepare Actor input
const input = {
"urls": [
{
"url": "https://example.com"
},
{
"url": "https://en.wikipedia.org/wiki/Web_scraping"
}
],
"mode": "screenshot"
};
// Run the Actor and wait for it to finish
const run = await client.actor("pennydata/shot-pdf").call(input);
// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
console.dir(item);
});
// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs
Python example
from apify_client import ApifyClient
# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")
# Prepare the Actor input
run_input = {
"urls": [
{ "url": "https://example.com" },
{ "url": "https://en.wikipedia.org/wiki/Web_scraping" },
],
"mode": "screenshot",
}
# Run the Actor and wait for it to finish
run = client.actor("pennydata/shot-pdf").call(run_input=run_input)
# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
print(item)
# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start
CLI example
echo '{
"urls": [
{
"url": "https://example.com"
},
{
"url": "https://en.wikipedia.org/wiki/Web_scraping"
}
],
"mode": "screenshot"
}' |
apify call pennydata/shot-pdf --silent --output-dataset
MCP server setup
{
"mcpServers": {
"apify": {
"type": "http",
"url": "https://mcp.apify.com/?tools=fetch-actor-details,pennydata/shot-pdf"
}
}
}
The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an Authorization: Bearer <APIFY_API_TOKEN> header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).
OpenAPI specification
Download the OpenAPI definition: https://api.apify.com/v2/actors/mKUrHZTYtNOuft0hb/builds/r3wP5F7bEtWm5BuPL/openapi.json