Bulk Website Screenshots & PDFs from URLs
Pricing
from $3.00 / 1,000 screenshot or pdfs
Bulk Website Screenshots & PDFs from URLs
Capture full-page or viewport screenshots (PNG, JPEG, WebP) or PDFs of a list of URLs. Device presets, wait-for-selector, custom CSS, ad blocking and best-effort cookie banner hiding. Accepts the same input as apify/screenshot-url. Failed URLs are free.
Pricing
from $3.00 / 1,000 screenshot or pdfs
Rating
0.0
(0)
Developer
Plainsource
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Website Screenshot & PDF Generator
Give this Actor a list of URLs and it saves a screenshot (PNG, JPEG or WebP) or a PDF of each page. You get one result row per URL with a link to the file, its size and the page title. If a URL fails, its row says why.
It accepts the same input as apify/screenshot-url, so you can switch without changing your input or integration. This is an independent Actor. It is not made or endorsed by Apify.
What it can do
- Full-page or viewport-only captures.
- Device presets: desktop (1920x1080), laptop (1366x768), iPhone (390x844 at 3x) and iPad (820x1180 at 2x), or any custom width, height and pixel ratio.
- PNG, JPEG or WebP with a quality setting, or PDF on A4 or Letter paper, with or without backgrounds.
- Wait for the network to go quiet, for a CSS selector to appear, or for a fixed delay. Scroll the page first so lazy-loaded images load.
- Hide elements by CSS selector, or add your own CSS.
- Hide cookie banners and pop-ups (best effort, see Limits). Nothing is clicked or accepted.
- Block 44 well-known ad and analytics services, so heavy pages load faster. You can turn this off.
- Capture several pages at once (1 to 10).
Input
The only required field is urls. Everything else has a default.
{"urls": [{ "url": "https://www.python.org" },{ "url": "https://news.ycombinator.com" }],"format": "png","fullPage": true,"device": "desktop"}
A mobile JPEG of the visible screen only, after a specific element has loaded:
{"urls": [{ "url": "https://www.bbc.com/news" }],"format": "jpeg","quality": 70,"device": "iphone","fullPage": false,"waitForSelector": "main"}
A PDF that looks like the page on screen:
{"urls": [{ "url": "https://en.wikipedia.org/wiki/Screenshot" }],"format": "pdf","pdfFormat": "A4","pdfMediaType": "screen"}
You can also point urls at a text file of links with { "requestsFromUrl": "https://example.com/my-urls.txt" }. Exact duplicate URLs are captured once.
Main settings
| Field | Default | What it does |
|---|---|---|
urls | Pages to capture. | |
format | png | png, jpeg, webp or pdf. |
fullPage | true | Capture the whole page. false captures the visible screen only. |
device | desktop | desktop, laptop, iphone, ipad or custom. |
viewportWidth, viewportHeight, deviceScaleFactor | 1280, 1080, 1 | Size for the custom device. |
quality | 80 | JPEG and WebP quality, 1 to 100. |
maxHeight | 15000 | Full-page captures stop at this height in CSS pixels, and the row is marked truncated. |
waitUntil | networkidle2 | load, domcontentloaded, networkidle2 or networkidle0. |
waitForSelector | A CSS selector that must appear before capturing. | |
delay | 0 | Extra wait in milliseconds before capturing. |
scrollToBottom | false | Scroll through the page first so lazy content loads. |
hideCookieBanners | true | Hide consent banners and pop-ups. |
blockAdsAndTrackers | true | Block common ad and analytics requests. |
selectorsToHide | CSS selectors to hide, one per line. | |
injectCss | Your own CSS, added to every page. | |
pdfFormat, pdfPrintBackground, pdfLandscape, pdfMediaType | A4, true, false, print | PDF options. |
maxConcurrency | 3 | Pages captured at the same time. |
navigationTimeoutSecs | 45 | How long to wait for a page's HTML to load. |
The Input tab in Console describes every field.
Switching from apify/screenshot-url
Your existing input works as it is. For example, this input written for apify/screenshot-url runs here without changes:
{"urls": [{ "url": "https://www.apify.com/" }],"format": "png","waitUntil": "load","delay": 0,"viewportWidth": 1280,"scrollToBottom": true,"delayAfterScrolling": 2500,"waitUntilNetworkIdleAfterScroll": false,"waitUntilNetworkIdleAfterScrollTimeout": 30000,"proxy": { "useApifyProxy": true },"selectorsToHide": ""}
What to know when you switch:
- Each result row has
url,screenshotUrlandscreenshotKey, the field names that Actor uses, so code that reads those fields keeps working. Rows also have more fields, listed under Output. - When you set
viewportWidthand nodevice, your width is used. - Pages are captured full-length by default. Set
"fullPage": falsefor the visible screen only. - The
proxyfield is accepted but ignored. This Actor connects to sites directly (see Limits). - To switch an API call or integration, replace the Actor ID with
plainsource/website-screenshot-pdf.
Output
Files go to the run's default key-value store. Each URL gets one row in the dataset. These rows come from a real run on 2026-10-21:
{"url": "https://www.python.org","finalUrl": "https://www.python.org/","status": "success","httpStatus": 200,"format": "png","device": "desktop","width": 1920,"height": 2632,"bytes": 698728,"screenshotKey": "www.python.org_1ab11d99cba1.png","screenshotUrl": "https://api.apify.com/v2/key-value-stores/NRCntiiTp8c3OoV1g/records/www.python.org_1ab11d99cba1.png?signature=QF9it6M9DdRhQdBSgAJH","title": "Welcome to Python.org","truncated": false,"hiddenOverlays": 0,"warnings": [],"capturedAt": "2026-10-21T15:39:04.949Z","error": null}
{"url": "https://www.nytimes.com","finalUrl": "https://www.nytimes.com/","status": "site_blocked","httpStatus": 403,"format": "png","device": "desktop","width": null,"height": null,"bytes": null,"screenshotKey": null,"screenshotUrl": null,"title": null,"truncated": false,"hiddenOverlays": null,"warnings": [],"capturedAt": "2026-10-21T15:39:10.491Z","error": "The site returned HTTP 403. This usually means it requires a login or blocks automated browsers. This Actor does not try to get around that."}
| Field | Meaning |
|---|---|
url | The URL you gave. |
finalUrl | The URL after redirects. |
status | success, failed, site_blocked (the site refused the browser), not_allowed (this Actor does not capture that URL) or skipped (your run's cost limit was reached). |
httpStatus | The HTTP status of the page. |
width, height | Image size in pixels. With pixel ratio 2 or 3, this is 2 or 3 times the CSS size. Empty for PDF. |
bytes | File size. |
screenshotKey | Record key in the run's key-value store. |
screenshotUrl | Link to the file. It works without an API token. |
title | The page title. |
truncated | true if the page was taller than maxHeight and only the top part was captured. |
hiddenOverlays | How many banners and pop-ups were hidden. |
warnings | Things worth checking, such as a page that never stopped loading. |
error | Why the URL failed. |
To get the results by API in one call:
curl -X POST "https://api.apify.com/v2/acts/plainsource~website-screenshot-pdf/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \-H "Content-Type: application/json" \-d '{"urls":[{"url":"https://www.python.org"}],"format":"jpeg","fullPage":false}'
Pricing
You pay a small fee when a run starts and a fixed price for each successful capture. Failed, blocked, not-allowed and skipped URLs are free. The current prices are on the Pricing tab. If you set a maximum cost for a run, the Actor stops starting new captures when the limit is reached and marks the remaining URLs as skipped.
Limits
- Public pages only. There is no input for cookies, logins or passwords. A page behind a login is captured as the login page.
- Sites that block automated browsers are reported, not bypassed. The Actor runs from Apify's servers, uses an unmodified headless Chrome and does not rotate IP addresses or use proxies. In a test run, nytimes.com returned HTTP 403, and that row was marked
site_blockedand not charged. - Some sites show their own error page with a normal status. In one test run booking.com returned an "Oops!" page with HTTP 200. The Actor cannot tell that apart from the real page, so it was captured and charged. Check the preview column.
- Not captured at all: linkedin.com, facebook.com, instagram.com, x.com, twitter.com and tiktok.com (including their short-link domains), because their terms forbid automated access. Local and private network addresses are refused too.
- Cookie banner hiding is best effort. It hides the containers of common consent tools and fixed overlays that cover the page. Banners from other tools, and consent pages that replace the whole site, can still appear. Use
selectorsToHidefor ones it misses. - Very tall pages are cut at
maxHeight(15,000 CSS pixels by default, 30,000 at most). WebP images can't be taller than 16,383 pixels. - Scroll-triggered content. Sections that only appear while you scroll can be blank. Turn on
scrollToBottomfor those pages. - Speed. Simple pages take about a second. Heavy marketing and news homepages took 15 to 45 seconds each in testing with the default 2 GB of memory.
- Fonts. Pages are rendered by Chrome on Linux, so fonts can look slightly different from macOS or Windows.
- Files are kept for your Apify plan's storage retention period. Download them if you need them longer.
Questions and problems
Open an issue on the Issues tab with the URL and the input you used.