Website Screenshot & PDF: Full Page, Most Cookie Banners Hidden avatar

Website Screenshot & PDF: Full Page, Most Cookie Banners Hidden

Pricing

$2.00 / 1,000 screenshot or pdf files

Go to Apify Store
Website Screenshot & PDF: Full Page, Most Cookie Banners Hidden

Website Screenshot & PDF: Full Page, Most Cookie Banners Hidden

Screenshots (PNG, JPEG, WebP) and PDFs of web pages or HTML. Full page with lazy images, mobile presets, common cookie banners hidden. You pay only for files produced.

Pricing

$2.00 / 1,000 screenshot or pdf files

Rating

0.0

(0)

Developer

Francesco Antonio Russo

Francesco Antonio Russo

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Website Screenshot & PDF – Full Page, Mobile, Common Cookie Pop-ups Hidden

Give it web addresses (or a piece of HTML) and get back a PNG, JPEG, WebP or PDF file for each one: the whole page with its lazy-loaded images, as a desktop, phone or tablet, with the common cookie banners and consent walls hidden. You pay only for a file that was produced and is not empty: a 404, a blocked page, a timeout or a bad address costs nothing.

For people who need page images or PDFs at scale: archiving and compliance snapshots, link previews, visual checks of a website on many screens, invoices and reports turned from HTML into PDF, thumbnails for a catalogue.

Price

One event: Screenshot or PDF file, $2 per 1,000 files ($0.002 per file). The event is charged only when a file was produced, is not empty and is stored in the key-value store of the run.

What you runFiles producedCost
The prefill (2 pages)2$0.004
100 pages100$0.20
1,000 pages, 20 of them are 404980$1.96
5,000 pages5,000$10.00
10,000 pages10,000$20.00

Free, never charged: an address that is not a valid web address (invalid_url), an address that is not http or https (for example ftp://) or that points inside a private network (blocked_unsafe_url), a host that does not exist or refuses the connection (unreachable), a page that answers an error such as 404 or 500 (http_error), a login wall, rate limit or bot challenge (blocked), a page that does not load in time (timeout), a capture that could not produce a file (empty_capture), and a page that came out as one flat colour with nothing on it (blank). Each of them still gets a record that says why. The spending limit you set on the run is respected exactly: the run stops before a file that would go over it. Apify's own platform fees, if any, are on the Pricing tab of this Actor.

What you can set

InputWhat it does
urlsThe addresses to capture (a list of addresses, or of {"url": "..."} objects). Only http and https.
htmlA complete HTML page to render instead of, or besides, the addresses (an invoice, a report). Relative addresses inside it cannot be resolved: use inline styles and data: or absolute https images.
formatpng (default), jpeg, webp or pdf.
fullPageCapture the whole page (default on) or only the first screen.
maxFullPageHeightTallest capture in CSS pixels, up to 16,384 (WebP: 16,383). A taller page is cut there and marked truncated.
qualityJPEG and WebP quality, 1 to 100 (default 80).
devicedesktop 1440x900 (default), desktop_hd 1920x1080, laptop 1280x800, iphone_15, iphone_se, pixel_8, ipad. Phones and the tablet also get a mobile browser identity and touch.
width, heightYour own screen size; they replace the preset (the record then says custom).
deviceScaleFactorPixel density 1 to 3 (2 = retina: twice as wide and tall). Default 1.
colorSchemelight (default) or dark, for sites that follow the system setting.
selectorCapture only one element, for example #pricing-table.
waitUntilload (default), domcontentloaded or networkidle (waits for a quiet network for at most 15 more seconds, and captures anyway if the page never gets quiet).
waitForSelectorWait (up to 20 seconds) for an element to exist before capturing.
delayMsExtra wait in milliseconds, 0 to 10,000.
scrollToBottomBefore a full page, a PDF or an element, scroll the page step by step so lazy-loaded images load (default on; at most 12 seconds and never beyond the height cap).
cookieBannershide (default) or off. Never "accept": this Actor gives no consent on your behalf.
hideSelectorsYour own list of CSS selectors to hide (chat widgets, sticky bars).
customCssCSS added to the page before the capture.
blockAdsDo not load a short fixed list of advertising networks (about 25 domains). Default off.
pdfFormat, pdfLandscape, pdfMargins, pdfPrintBackground, pdfMediaPDF paper size (A3, A4, A5, Letter, Legal, Tabloid), orientation, margins (default 10 mm), backgrounds (default on), and whether the print styles (default) or the screen styles are used.
cookies, headers, basicAuthYour own session cookies, HTTP headers and basic-auth login for pages you may capture. Stored as secrets, never written to the log or the output. Cookies need a domain or url and are sent only there; headers and basic auth are sent only to the address of the page itself, never to the third-party files it loads.
timeoutSecsTime given to one address, 2 to 120 (default 45). A timeout, a reset connection or a 5xx answer is tried once more.
maxConcurrencyPages in parallel, 1 to 6 (default 3).

Options that do not apply to the chosen format (for example selector with pdf) are listed as warnings in the log and in the SUMMARY.

Example input (this is the prefill):

{
"urls": [
{ "url": "https://www.python.org/" },
{ "url": "https://en.wikipedia.org/wiki/Web_scraping" }
]
}

What you get

One record per address (and one for the html input) in the dataset, and one file per record in the key-value store of the run. Records are written as captures finish: index is the position of the entry in your input.

FieldMeaning
indexPosition of the entry in your input, counting from 0 (an address repeated later in the list has no record of its own, so the numbers can skip; the HTML page, if any, comes after all the addresses).
inputTypeurl or html.
urlThe address you gave (null for HTML).
finalUrlWhere the page ended after redirects.
statusok or the free reason (see below).
httpStatusHTTP status of the page itself.
titleTitle of the page.
formatpng, jpeg, webp or pdf (null when there is no file).
fileUrlPublic link to the file (works without a token; it lives as long as the storage of the run).
fileKeyKey of the file in the key-value store.
bytesSize of the file.
width, heightSize of the image in pixels as produced (CSS pixels times deviceScaleFactor); null for PDF.
fullHeightPxHeight of the whole page in CSS pixels.
truncatedTrue when the page was taller than the cap and the image was cut.
pagesNumber of pages of a PDF.
deviceThe preset used, or custom.
durationMsTime spent on this entry.
errorWhy there is no file.
capturedAtWhen the record was written.

A real record (from a run on 2026-10-15; the link of your run has your store id and a signature):

{
"index": 0,
"inputType": "url",
"url": "https://www.python.org/",
"finalUrl": "https://www.python.org/",
"status": "ok",
"httpStatus": 200,
"title": "Welcome to Python.org",
"format": "png",
"fileUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/shot-0001-www-python-org.png?signature=<signature>",
"fileKey": "shot-0001-www-python-org.png",
"bytes": 488595,
"width": 1440,
"height": 2549,
"fullHeightPx": 2549,
"truncated": false,
"pages": null,
"device": "desktop",
"durationMs": 4209,
"error": null,
"capturedAt": "2026-10-15T09:10:08.749Z"
}

A free record, from the same kind of run:

{
"index": 5,
"inputType": "url",
"url": "https://httpbin.org/status/404",
"finalUrl": "https://httpbin.org/status/404",
"status": "http_error",
"httpStatus": 404,
"title": null,
"format": null,
"fileUrl": null,
"fileKey": null,
"bytes": 0,
"width": null,
"height": null,
"fullHeightPx": null,
"truncated": false,
"pages": null,
"device": "desktop",
"durationMs": 642,
"error": "the page answered HTTP 404",
"capturedAt": "2026-10-14T15:32:07.789Z"
}
statusMeaningCharged
okA file was produced and stored.yes
invalid_urlNot a web address (or credentials inside the address: use basicAuth).no
unreachableThe name does not resolve, or the host refused or dropped the connection.no
http_errorThe page answered 4xx or 5xx other than 401, 403 and 429. No file is saved, not even of the error page.no
blocked401, 403, 429, or a bot challenge page ("Just a moment", "Attention Required", or a CDN challenge that answers 202 with an empty page, or a short block page that answers 200 with a known sentence such as "You've been blocked by network security" or "Access denied"). A page with a lot of text is never taken for a block page because it contains those words. No attempt is made to get around it.no
timeoutNot captured within timeoutSecs (after one more attempt), or waitForSelector never showed up.no
blocked_unsafe_urlNot http or https, or an address inside a private network, loopback, link-local or cloud-metadata range, also after redirects.no
empty_captureThe browser could not produce a file: the selector matches nothing, the address is a file download, the tab crashed, or the image came out empty.no
blankThe picture of the page is one flat colour (99.9% of the pixels) and the page has no text and no pictures of its own, typically a challenge page or a page that never rendered. Only whole-page images are judged (not PDF, not a selector capture); a page with any text, logo or picture is never blank. If it is a page that needs more time, raise delayMs.no

A run also writes a SUMMARY record: files produced, files charged, free records by reason, why the run stopped (done, budget exhausted, time limit, aborted), warnings and a few counters. If every address of a run is invalid, the run still ends normally with one free record per address.

How it works, and what it will not do

It opens each page in Chromium (Playwright), waits for it, scrolls through it so lazy images load, hides what you asked to hide and takes the picture or prints the PDF. It identifies itself honestly: the user agent of Chromium plus (compatible; WebsiteScreenshotPDF/0.1), the name of this Actor (https://apify.com/far003/website-screenshot-pdf). The link is not in the user agent because some publishers refuse any agent that names a scraping platform.

It does not: solve CAPTCHAs, mask itself as a normal browser, rotate proxies, fake a location, click "Accept" on consent banners, or sign in for you. A page behind a login is captured only with the cookies, headers or login that you provide. Some sites refuse automated visitors that say who they are; you then get a free blocked record (in a test on 2026-10-14 a large news site and a photo site both answered 403).

Safety. Every connection of the browser goes through a filter that resolves the name itself and connects only to a checked public address. Private networks (10.x, 172.16-31.x, 192.168.x), loopback, link-local and cloud metadata addresses are refused for the page you ask for, for its redirects and for everything the page loads, so an address you give, or a page you capture, cannot be used to reach into the machine that runs the Actor. Mail, shell and database ports are refused too.

Memory and speed

Default memory is 2,048 MB (minimum 1,024, maximum 4,096). Peaks measured on a laptop (macOS, resident memory of Node plus Chromium; Linux numbers can differ):

RunPeak
The prefill, 2 pages, 3 in parallelabout 1.1 GB
3 very tall pages (cut at 16,384 px), density 1, run memory 2,048 MBabout 1.8 GB
One 1440 x 16,384 page at deviceScaleFactor 2 (image 2880 x 32,768)about 2.3 GB
3 of those, run memory 4,096 MBabout 3.3 GB

Pages load in parallel, but turning a tall page into an image waits its turn when the memory of the run would not hold both: this is why a run with little memory is slower, not killed. A single capture that is bigger than the memory of the run (retina on a very tall page with 2,048 MB) runs alone and may still run out of memory: use 4,096 MB for that, or lower deviceScaleFactor or maxFullPageHeight. A typical page takes 2 to 12 seconds; a very tall page about 10 seconds.

Limits, honestly

  • Height. Chromium cuts or empties images taller than 16,384 pixels (WebP: 16,383 pixels of the file: with deviceScaleFactor 2 a WebP is cut at 8,191 CSS pixels, with 3 at 5,461). Such a page is captured up to the cap and the record says truncated: true and gives the real height in fullHeightPx. Use a PDF to get a very long page whole.
  • Single-page apps. With the default waitUntil: load an app that draws its content after the page has loaded can be captured as its loading skeleton, and it is charged as a file. If the pictures show placeholders, use waitUntil: networkidle (or waitForSelector on an element that only exists once the content is there).
  • PDF of a long page. The PDF is what the browser prints. A page that scrolls inside its own container (a fixed-height app or an article frame) or whose print style hides the content can come out as one page; the record gives the number of pages in pages: check it, or try pdfMedia: screen.
  • Lazy loading is woken by scrolling, with a time cap. A page that grows forever (endless scroll) is captured up to the cap; content that needs a click, a login or a long animation may not be there. Sections sized to the screen height (100vh) can look stretched in a full-page image.
  • Cookie banners are hidden by a list of the common consent platforms (OneTrust, Cookiebot, Didomi, Usercentrics, Quantcast, Sourcepoint and others); it was checked on real pages for OneTrust and Cookiebot, and the consent walls that cover the whole page and lock its scroll of Le Monde, Le Figaro, Marca, Corriere della Sera and El País are hidden too (the page is freed, so a full page is captured). The list is not complete. A banner that is not recognised stays; send its selector in hideSelectors. The list never hides a page wrapper, the body or anything that contains the main content.
  • A login redirect is a page. A page that sends you to a login page is captured as that login page (status: ok, and finalUrl shows it): check finalUrl if that matters to you. It is charged like any file.
  • HTML input cannot load relative files. The sandbox page has no real address.
  • DNS. The address check and the connection use the same checked address, so a name that changes its answer in the middle cannot slip a private address in.
  • No guarantee from the sites. Pages change, block or go down; a file reflects the page at the moment of the capture.

FAQ

Do I pay for pages that fail? No. Only a produced, non-empty, stored file is charged. You can see every free record and its reason in the dataset.

Why did I get blocked? The site answered 401, 403 or 429, or showed a bot challenge or a short block page (also when its code is 200). This Actor does not try to get past that. If you are allowed to see the page, pass your own cookies, headers or basicAuth.

Can it capture pages behind a login? Yes, with your own session cookie (or header, or basic auth). They are secret inputs and are never logged or put in the output.

Does it accept cookie banners? No. It hides the common ones, because accepting is a consent that only you can give. Use cookieBanners: "off" to see the page as a first-time visitor does.

How do I get a mobile screenshot? Set device to iphone_15, iphone_se, pixel_8 or ipad, and deviceScaleFactor to 2 for a sharp image.

How do I turn an invoice into a PDF? Put the HTML in html, set format to pdf, and choose pdfFormat and pdfMargins. Styles inline or in a <style> tag; images as data: addresses.

The page is taller than 16,384 pixels. The image is cut at the cap and marked truncated. For the whole page use pdf, or capture sections with selector.

How long are the files kept? In the key-value store of the run, for as long as your Apify plan keeps the storage of runs. Download or copy what you need to keep.

Call it from code

Replace <APIFY_TOKEN> with your token.

curl -X POST "https://api.apify.com/v2/acts/far003~website-screenshot-pdf/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"urls": [{"url": "https://example.com"}], "format": "webp", "device": "iphone_15"}'
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<APIFY_TOKEN>' });
const run = await client.actor('far003/website-screenshot-pdf').call({
urls: [{ url: 'https://example.com' }],
format: 'png',
fullPage: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) console.log(item.status, item.fileUrl);

Your responsibility

You are responsible for having the right to capture the pages you give, and for what you do with the files: copyright, terms of the sites and privacy law (such as the GDPR) apply to a screenshot as to any copy. This Actor does not look for personal data and stores nothing but the file you asked for and the record that describes it.