Website Screenshot & PDF Capture + Change Alerts avatar

Website Screenshot & PDF Capture + Change Alerts

Pricing

from $3.20 / 1,000 captures

Go to Apify Store
Website Screenshot & PDF Capture + Change Alerts

Website Screenshot & PDF Capture + Change Alerts

Take website screenshots of any URL list: full page, viewport or one page element, in PNG, JPEG or WebP at desktop, tablet and phone sizes. Optional URL to PDF. Each row has a file link. Visual change detection compares with the last run and returns a diff image.

Pricing

from $3.20 / 1,000 captures

Rating

0.0

(0)

Developer

Malik Said

Malik Said

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

18 hours ago

Last modified

Share

Take screenshots of a list of web pages. Each URL is captured at the screen sizes you choose: desktop, laptop, tablet, phone or a custom size. You get full-page or above-the-fold images as PNG, JPEG or WebP, and an optional PDF of each page (URL to PDF). It can also turn raw HTML into an image or a PDF. Every file gets a download link in the dataset.

Turn on visual change detection and schedule the Actor. Each run compares every screenshot with the one from the last run. The row tells you whether the page changed and by how much. Changed pages also get a diff image with the changed pixels in red.

What you can use it for

  • Website monitoring: see when a competitor, a partner or your own site changes its look.
  • Visual regression checks after a deploy, at several screen sizes in one run.
  • Archiving pages as PDF or images for records, reports or compliance files.
  • Thumbnails and previews for directories, link lists or SEO reports.

How to use it

  1. Paste your URLs, one per line.
  2. Pick the viewports. The default is desktop (1440x900) and phone (390x844).
  3. Choose full page or viewport only, and the image format.
  4. Optional: turn on "Also save a PDF".
  5. Optional: turn on "Visual change detection" and schedule the Actor daily or weekly.

Each URL and viewport pair is one capture. Ten URLs at two viewports make 20 captures. A PDF counts as one more capture per URL.

Input example

{
"urls": ["https://nodejs.org", "https://www.python.org"],
"viewports": ["desktop", "phone"],
"fullPage": true,
"format": "webp",
"savePdf": true,
"compareWithPrevious": true,
"stateKey": "my-watch-list"
}

Other options:

  • Hide cookie banners (on by default). The Actor hides common consent banners with CSS. It does not click or accept anything.
  • Hide elements. CSS selectors of extra elements to hide, such as chat widgets.
  • Block ads and trackers (off by default). The Actor blocks requests to common ad and tracker hosts of other sites before the page loads. Pages load faster, and the row says how many requests were blocked in adsBlocked.
  • Proxy with country choice (off by default). Use Apify Proxy and pick a country to see a page as visitors there see it: local prices, language or region banners. Through a proxy, video and audio are not loaded, and a page stops loading new files after about 15 MB. Each capture through a proxy adds a "Proxy capture" charge (see Pricing). The proxy is for country choice only: pages with a bot check are still skipped.
  • Pixel density (scale). 1, 2 or 3. Use 2 or 3 for sharp retina-style images, for example phone captures for app store pages or marketing. Files are larger. imageWidth and imageHeight are in real pixels. To keep runs stable, a full page at 2 or 3 stops at the pixel count of a default desktop capture: about 2,000 page pixels tall for desktop at 2, and about 3,280 for a phone at 3. Such rows say truncated: true.
  • Colour scheme. Light or dark. Sites that support dark mode show their dark theme.
  • Capture one element. A CSS selector such as #pricing. The Actor captures only the first matching element. If it is missing, the Actor captures the page and the row says elementFound: false. PDFs ignore it.
  • Wait for element. A CSS selector to wait for, up to 15 seconds, before the capture. Use it for pages that render late. If the element never appears, the capture goes ahead and the row says waitSelectorFound: false.
  • Extra wait. Seconds to wait before the capture, for animations.
  • Scroll to load lazy images. For full-page captures.
  • Maximum page height. Very long pages are cut at this height (default 8,000 pixels). The row then says truncated: true.
  • Change threshold. The share of pixels that must differ before a page counts as changed. The default is 0.1%.
  • Maximum captures. The default is 100. Set 0 for no limit.

Output example

This row comes from a real run. It is the second run with change detection on the same state key.

{
"id": "8cbaec05ec",
"url": "https://nodejs.org/",
"status": "captured",
"reason": null,
"finalUrl": "https://nodejs.org/en",
"pageTitle": "Node.js — Run JavaScript Everywhere",
"httpStatus": 200,
"type": "screenshot",
"viewport": "desktop",
"viewportWidth": 1440,
"viewportHeight": 900,
"fullPage": true,
"format": "webp",
"fileKey": "nodejs-org-desktop-8cbaec05ec.webp",
"fileUrl": "https://api.apify.com/v2/key-value-stores/pIgZAp3VJh6Th6gCR/records/nodejs-org-desktop-8cbaec05ec.webp?signature=oJg1sTEQxCTugwpPyqw4",
"fileSizeBytes": 76604,
"imageWidth": 1440,
"imageHeight": 985,
"pageHeight": 985,
"truncated": false,
"previousCapturedAt": "2026-10-21T14:45:51.091Z",
"changed": true,
"diffPercent": 0.106,
"diffImageUrl": "https://api.apify.com/v2/key-value-stores/pIgZAp3VJh6Th6gCR/records/nodejs-org-desktop-8cbaec05ec-diff.png?signature=J486WGbkLgMZui6H6yIQ",
"scrapedAt": "2026-10-21T14:51:34.290Z"
}

A URL that the Actor did not capture gets a free row with the reason:

{
"id": "b65c46d974",
"url": "https://www.reuters.com/world/",
"status": "skipped",
"reason": "robots.txt disallows this page.",
"httpStatus": null,
"viewport": "desktop",
"type": "screenshot",
"scrapedAt": "2026-10-21T14:47:23.691Z"
}

The files are in the run's key-value store. The fileUrl link opens the file without an API token. The dataset has two views: "Captures" and "Changed pages".

Can I capture one part of a page?

Yes. Set Capture one element to a CSS selector. This example watches one pricing box for changes:

{
"urls": ["https://example.com/pricing"],
"captureSelector": "#pricing",
"waitForSelector": "#pricing",
"compareWithPrevious": true,
"stateKey": "pricing-box"
}

HTML to PDF or PNG

Send raw HTML when the page has no public URL, such as an invoice, a report or a social card. Clear the URLs list to capture only the HTML. Each document is up to 2 MB, and 5 MB in total per run. Remote images and fonts in it load as usual, and each remote host's robots.txt applies. Local files never load.

{
"urls": [],
"htmlDocuments": ["<html><body><h1>Invoice 1042</h1><p>Total: $49</p></body></html>"],
"viewports": ["desktop"],
"savePdf": true
}

The row's url is html:0 for the first document, and source is html.

Local language, time zone and country

Many sites change language, date format or opening hours by visitor. Set all three to see the page as a local visitor sees it:

{
"urls": ["https://example.com"],
"locale": "de-DE",
"timezoneId": "Europe/Berlin",
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyCountry": "DE" }
}

Fields

FieldMeaning
statuscaptured, skipped (robots.txt or a bot check) or failed (load error or HTTP error)
type, formatscreenshot or pdf; png, jpeg, webp or pdf
viewport, viewportWidth, viewportHeightScreen size used
fileUrl, fileKey, fileSizeBytesThe saved file
imageWidth, imageHeight, pageHeight, truncatedImage and page size
finalUrl, pageTitle, httpStatusPage details after redirects
changed, diffPercent, diffImageUrl, previousCapturedAtChange detection results. Null on the first run
captureSelector, elementFoundThe element captured, and whether it was found. Null when you capture the whole page
waitSelectorFoundWhether the wait-for element appeared. Null when you set no wait selector
scale, colorSchemePixel density (1, 2 or 3; null for PDFs) and light or dark mode
adsBlockedAd and tracker requests blocked on the page. Null when ad blocking is off
proxyCountryProxy country used, any for Apify Proxy without a country, custom for your own proxy URLs. Null without a proxy
maskedCountPage elements covered by a grey box (Mask elements). 0 when none
locale, timezoneIdBrowser language and time zone used. Null when not set
sourceurl for a web page, html for an HTML document from the input

How change detection works

The Actor keeps the last screenshot of each URL and viewport in a named key-value store. The store is called website-screenshot-pdf-state, and the screenshots are kept under your state key. On the next run it compares the new screenshot with the stored one, pixel by pixel. A pixel counts as changed when a colour channel moves by more than 24 of 255. This ignores tiny rendering noise. A page that got taller or shorter counts the extra area as changed. Then the new screenshot becomes the baseline for the next run.

Use one state key per watch list. Pages with rotating banners, live counters or ads will show small changes on every run. Turn on "Block ads and trackers", or cover moving parts with "Mask elements". A masked part becomes a grey box in every capture, so it never counts as a change, and the layout below it does not move. "Hide elements" removes an element instead, which can shift the page. A capture at another scale, in dark mode, or with another locale or time zone keeps its own baseline.

Pricing

You pay per event:

  • $0.005 when the run starts, for each GB of memory (one event at the default 1 GB).
  • $0.004 per capture (one screenshot or one PDF), which is $4 per 1,000 captures. On the Gold, Platinum and Diamond plans it is $0.0032, which is $3.20 per 1,000. Change detection and diff images are included.
  • Skipped and failed URLs are free.
  • $0.05 per capture through a proxy (optional), on top of the capture price, which is $50 per 1,000. Proxy traffic has its own cost. Captures without a proxy never pay it.

Example: 50 URLs at desktop and phone size make 100 captures. That run costs $0.405 ($0.005 + 100 x $0.004), or $0.325 on Gold. The same run through a proxy costs $5.405.

FAQ

How do I stop false change alerts? Add the moving parts to Mask elements, for example ["time", ".ticker", "#last-updated"]. Turn on Block ads and trackers for pages with ads.

Why was a page skipped? Its robots.txt disallows it, or it showed a bot check. Skipped and failed pages are free and listed with a reason.

How long can a full page be? Up to Maximum page height (8,000 pixels by default, 16,000 at most). Longer pages are cut and marked truncated: true.

Can it log in to a page? No. It captures public pages only.

Why does a page look different from my browser? Cookie banners are hidden by default. Language, time zone and country can differ: set Locale, Time zone and a proxy country.

How do I get change alerts by email or Slack? Schedule the Actor with change detection on. Then add an Apify integration (email, Slack or a webhook) and use the "Changed pages" view.

Does masking hide personal data? Yes. A masked element is a solid box in the file.

Use it from the API or an AI agent

One call runs the Actor and returns the rows, each with a fileUrl you can open without a token:

curl -X POST "https://api.apify.com/v2/acts/maliksaid~website-screenshot-pdf/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"urls": ["https://example.com"], "viewports": ["desktop"]}'

AI agents can call it through the Apify MCP server (mcp.apify.com) by its name, maliksaid/website-screenshot-pdf.

Good to know

  • The Actor reads each site's robots.txt first and skips pages it disallows. This cannot be turned off.
  • It uses a normal headless Chromium browser. It does not solve CAPTCHAs, log in or hide that it is a browser. Sites that show a bot check or answer 403 are listed as skipped or failed, at no charge.
  • Phone and tablet captures use the screen width, so pages show their responsive layout. The browser does not pretend to be a phone.
  • Only capture pages you are allowed to copy. Some sites' terms limit how you may reuse their content.
  • Default memory is 1 GB. For long lists, 2 GB runs more pages at once.