Website Screenshot & Change Monitor (PDF, Markdown)
Pricing
from $6.00 / 1,000 page checkeds
Website Screenshot & Change Monitor (PDF, Markdown)
Screenshot hundreds of URLs or a whole sitemap as PNG, JPEG or PDF, on desktop and mobile, and get alerted when a page changes: diff image in red, text added and removed, price and stock changes, Slack or Discord alerts. Markdown and JSON-LD for AI. Failed pages are free.
Pricing
from $6.00 / 1,000 page checkeds
Rating
0.0
(0)
Developer
Sinan Dogan
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
16 hours ago
Last modified
Categories
Share
What does Website Screenshot & Change Monitor do?
Screenshot hundreds of pages, and know the moment one changes. Website Screenshot & Change Monitor captures a list of URLs or a whole sitemap as PNG, JPEG or PDF in a real Playwright browser, on desktop and mobile, then compares every page with the previous run: visual diff, text added and removed, price and stock. Three tools in one run: a bulk website screenshot API, a website change monitor with alerts, and a web page to Markdown extractor for AI.
- 📸 Clean screenshots in bulk: desktop, Retina, iPhone, Pixel and iPad presets (several devices in one run), full page or a single element, PDF in A4, Letter, Legal or A3. Cookie banners, chat widgets and ads are hidden for you.
- 🔍 See exactly what changed: share of changed pixels, a diff image with the changes in red, the lines of text added and removed, and ignore regions for clocks and carousels.
- 🏷️ Competitor price and stock tracking: schema.org product price and availability compared from run to run, with the old and new values.
- 🔔 Alerts where you work: Slack and Discord messages with the diff image, Telegram, or any webhook (n8n, Make, Zapier).
- 🤖 AI and RAG ready: visible text as Markdown or plain text, metadata (canonical URL, language, Open Graph) and JSON-LD structured data.
- 🔐 Pages behind a login: session cookies or HTTP headers, stored encrypted and sent only to the captured site.
- 💲 $6 per 1,000 pages, everything included. Failed pages (blocked, not found, timed out) are never charged.
Who uses it:
| You are | You use it to |
|---|---|
| E-commerce teams | Watch competitor product pages and get alerted when a price drops or an item goes out of stock. |
| Agencies and QA teams | Produce visual reports for clients and check every page of a site on desktop and mobile after each release. |
| Compliance, legal and marketing | Archive dated captures of terms, pricing pages and ads, and be told when a competitor changes its messaging. |
| AI builders | Turn sitemaps into Markdown for RAG pipelines and keep them fresh by re-crawling only what changed. |
How to take website screenshots in bulk
- Keep the two example URLs, or enter two public pages of your own.
- Keep the custom 1280 × 800 viewport and PNG format for a quick first run.
- Click Start, then inspect image links, dimensions and status in the dataset.
- Open
screenshotUrlto download each image. Download the dataset separately as JSON, HTML, CSV or Excel; these exports contain links and metadata, not an archive of image files.
{"startUrls": [{"url": "https://docs.apify.com"},{"url": "https://www.wikipedia.org"}],"device": "custom","viewportWidth": 1280,"viewportHeight": 800,"fullPage": false,"format": "png"}
Why use this screenshot API?
- One batch, explicit results: successful files and failed URLs stay visible in one dataset.
- Mobile and desktop presets: iPhone, Pixel, iPad and desktop/Retina settings include pixel density, touch and browser context.
- Several devices in one run: select desktop and mobile presets together in Several devices to get every URL on each device.
- Sitemaps: enter a
sitemap.xml(sitemap indexes and.xml.gzfiles included) and filter its pages with include and exclude patterns. - Content preparation: optional scrolling, dark mode, hidden selectors and extra delay.
- Clean captures: Hide distractions (on by default) removes live-chat widgets (Intercom, Drift, Crisp, HubSpot, Zendesk, Tawk.to, LiveChat, Tidio and more), hides ad slots while keeping their space, finishes animations and pauses videos.
- Dynamic sections: wait for a visible CSS selector and optionally capture just that element as PNG/JPEG.
- Cookie-banner handling: overlays of common consent platforms (OneTrust, Didomi, Cookiebot, Quantcast, Usercentrics, TrustArc, Sourcepoint, Axeptio and more) are hidden before the capture, and an accept button is clicked when found, including in consent frames and open shadow roots. Best effort, not a guarantee for every website. Disable it to preserve the initial consent screen.
- Long pages: full-page captures taller than the image limit (about 60,000 pixels) are split into several images by default (
partUrls), so nothing is lost. Choose Cut at the maximum height to keep one image, markedtruncated: true. - PDF settings: A4, Letter, Legal or A3, portrait or landscape, with or without margins.
- Pages behind a login: pass session Cookies or HTTP headers (stored encrypted, never logged, sent only to the captured site by default), and capture in another Language or Time zone.
- Download everything at once: the Output tab links to a ZIP archive of all screenshots of the run.
- Change monitoring: compare every page with the previous run, report
changed,changePercent,textChangedand the changed lines, get a diff image, ignore dynamic regions, keep only changed pages, and get a chat or webhook notification. - Text, metadata and structured data for AI: visible page text as plain text or Markdown, description, canonical URL, language, first heading, Open Graph tags, and JSON-LD with a price and availability summary for products.
- Runs that finish: blocked, timed-out or unreachable pages get a
faileditem with the reason; the run still succeeds, so schedules and integrations keep working.
Capture pages from a sitemap
Add a sitemap to URLs: any URL whose path looks like /sitemap.xml, /sitemap_index.xml, /post-sitemap.xml, or any .xml.gz file, is read instead of captured. Sitemap indexes are followed (up to 3 levels and 50 sitemap files), and gzip-compressed sitemaps are unpacked automatically.
- Sitemap: include URLs matching keeps only pages whose URL matches a regular expression (case-insensitive), e.g.
/blog/or/products/[^/]+$. - Sitemap: exclude URLs matching drops matching pages, e.g.
/tag/|/page/\d+. - Sitemap: max pages (default 100, up to 1,000) caps the pages taken from sitemaps, in sitemap order. Ordinary start URLs are always captured on top, and a page that is both a start URL and in the sitemap is captured once.
{"startUrls": [{ "url": "https://docs.apify.com/sitemap.xml" }],"urlIncludePattern": "/actors/development/","urlExcludePattern": "/input-schema","maxSitemapUrls": 20,"format": "jpeg"}
Reading sitemaps is free; each page checked is charged as usual. The log and the SUMMARY record show how many sitemaps were read, how many pages they list and how many were selected. Sitemaps are downloaded directly, without the proxy. HTTP headers and Cookies follow the same scope as page captures (see Capture pages behind a login): headers go only to the host of the sitemap URL you entered, so a nested sitemap or a redirect on another host (a CDN, for example) never receives them unless Send headers to every domain is on; cookies go to the hosts they cover. A sitemap that cannot be read is logged as a warning and the run continues with the other URLs. Patterns are matched against the full URL, so check the paths the sitemap actually lists (they can differ from the address you see in the browser).
Capture a dynamic section
Set Wait for element to the selector that appears when the content is ready. Capture element saves the first matching element and overrides full-page image capture. Clear that selector for PDF output; PDFs always cover the page.
{"startUrls": [{"url": "https://docs.apify.com"}],"waitForSelector": "main","captureSelector": "main","format": "png","selectorTimeoutSecs": 30}
An absent element produces a failed item after Element wait timeout. The Actor disables CSS animations during image capture for more consistent files.
Monitor pages for changes
Turn on Monitor changes and run the Actor on a schedule, for example daily. The first run saves a baseline (changed: null). Each later run compares every page with its previous capture, for the same URL, device and capture settings, and reports:
changed:truewhen more than Change threshold percent of the pixels differ (any difference with the default 0),falseotherwise. For PDF output only the text is compared, since PDF files change on every export.changePercent: share of differing pixels, measured by the browser on the first image of the page.textChanged: whether the visible text, of the page or of Capture element, changed.textChanges: the lines of textaddedandremovedsince the previous run, in page order (up to 50 lines each, 300 characters per line;truncated: truewhen some were left out). The first 20,000 characters of each page's text are compared line by line. It isnullwhen the text did not change, and on the first run after an update of the Actor, since earlier runs did not store the text.diffImageUrl: a copy of the screenshot with the changed pixels highlighted in red, for changed PNG/JPEG pages. Very large captures (above 10 million pixels) get no diff image;diffImageNoteexplains why.previousCapturedAtandpreviousScreenshotUrl: when and what the page looked like before (the link stays valid while the previous run's storage is retained).- With Extract structured data,
priceChanged,previousPrice,priceChangePercent,availabilityChangedandpreviousAvailability(see Monitor prices and stock); a price or stock change also counts as a change.
Only changed pages keeps the dataset and storage small: unchanged pages get no item and no saved image. The previous capture of each page, with its text, is kept in a named key-value store (Monitoring store name, default website-screenshot-monitor) that persists across runs; use a different name for each independent watch list.
Clocks, counters and carousels change on every run. Hide distractions (on by default) already removes chat widgets, hides ad slots and stops animations. For anything else, list the dynamic areas in Ignore regions (e.g. #clock, .hero-carousel): they are masked in a separate comparison image and their text is left out of textChanged, while the delivered screenshot still shows them. You can also capture a stable section with Capture element, hide elements entirely with Hide elements, or raise Change threshold (e.g. 0.5). Ads loaded by video or outstream players that use no standard ad container may not be hidden; add their selector to Ignore regions or Hide elements.
{"startUrls": [{ "url": "https://example.com/pricing" }],"captureSelector": "main","monitorChanges": true,"onlyChanges": true,"changeThresholdPercent": 0.5,"ignoreSelectors": ["#live-visitors", ".promo-carousel"],"stateStoreName": "competitor-pricing","notificationWebhookUrl": "https://hooks.slack.com/services/..."}
Change notifications
Set Notification webhook URL to receive one POST per run when at least one page changed. The URL is stored encrypted and never logged. A failing webhook is logged as a warning and never fails the run.
| Destination | URL | Body |
|---|---|---|
| Slack | Incoming webhook https://hooks.slack.com/services/... | Summary text, then the diff images (up to 10) |
| Discord | Channel webhook https://discord.com/api/webhooks/... | Summary text, then the diff images as embeds (up to 10); mentions in page text never notify anyone |
| Telegram | https://api.telegram.org/bot<token>/sendMessage?chat_id=<chat id> | Summary text with links to the screenshots and diff images |
| Other | Any HTTPS endpoint (Make, Zapier, n8n, your API) | JSON: event, changedCount, checkedCount, actorRunId, datasetId, pages[] with textChanges |
The summary lists each changed page with its share of changed pixels and its first text changes, above the links:
1 of 3 monitored page(s) changed:- https://example.com/pricing (2.1% of pixels, text changed)− Pro plan $20/month+ Pro plan $24/monthhttps://api.apify.com/v2/key-value-stores/.../records/screenshot-....pngchanges: https://api.apify.com/v2/key-value-stores/.../records/diff-....png
Up to 3 removed and 3 added lines are shown per page; the dataset has the full list. Slack and Discord display diff images only when the key-value store is reachable by them (it is on the Apify platform); if Slack refuses an image, the message is resent without images.
Read the change report
Every run writes REPORT (Markdown) to the default key-value store; open it from the Markdown report output tab. It lists:
- Changed pages first, largest change first: changed pixels (%), up to 5 removed and 5 added text lines per page, the price change (old → new) and stock change when price monitoring is on, and links to the screenshot and the diff image;
- failures, with the reason for each page that failed or was skipped;
- the number of unchanged pages.
Text, prices and error messages come from the captured sites, so the report escapes them: a page cannot inject links, tables or HTML into it. Full details stay in the dataset (textChanges, previousPrice, errorMessage).
Extract text, metadata and structured data
Extract page text adds the visible text of the page, or of Capture element, to each result: plain text, or Markdown that keeps headings, lists, links and tables. Text longer than Max text length (20,000 characters by default) is cut and marked textTruncated: true. Extract metadata adds the meta description, canonical URL, language, first h1 and Open Graph tags. All come from the same page load as the screenshot.
Extract structured data reads the page's JSON-LD (<script type="application/ld+json">, used by Shopify, WooCommerce, news sites and most CMSs) into structuredData:
product: name, SKU, brand,price,priceCurrencyandavailability(e.g.InStock) of a schema.org Product. Prices like19.99become numbers; ambiguous text such as19,99orfrom $10is kept as text. An AggregateOffer gives its lowest price.article: type, headline, publication and modification dates and author of an Article, NewsArticle or BlogPosting.types,jsonLd: every schema.org type found, and the parsed blocks (capped at 50,000 characters;jsonLdTruncatedtells when blocks were left out). Invalid blocks are skipped and counted ininvalidJsonLdCount.
Combined with Monitor changes, this also turns on price and stock monitoring (next section).
Monitor prices and stock
With Monitor changes and Extract structured data both on, the product's price, priceCurrency and availability are stored with each page's monitoring state, and every later run reports:
priceChanged: whether the price or its currency changed since the previous run;previousPriceis the old price andpriceChangePercentthe change in percent (null when a price is text, like19,99, or the old price is 0).availabilityChangedandpreviousAvailability: stock changes, e.g.InStocktoOutOfStock.
All five are null on the first run, when a run has no structured price (or availability), and when Extract structured data was off in either run. A price or stock change sets changed: true even when the screenshot changed less than Change threshold, so it is kept by Only changed pages and sent to the Notification webhook URL, where the summary reads price 24.99 USD → 19.99 USD (-20%) and availability InStock → OutOfStock; generic webhooks get priceChange and availabilityChange objects per page. The Prices and stock dataset view lists these fields. Price comparison is included in the page event: there is no extra charge.
{"startUrls": [{ "url": "https://shop.example.com/products/example-mug" }],"monitorChanges": true,"extractStructuredData": true,"onlyChanges": true,"changeThresholdPercent": 1,"stateStoreName": "price-watch"}
{"startUrls": [{ "url": "https://docs.apify.com/platform/actors" }],"extractText": true,"textFormat": "markdown","maxTextLength": 20000,"extractMetadata": true,"extractStructuredData": true}
Capture pages behind a login
Use a session cookie or an HTTP header from a logged-in browser session or an API token:
{"startUrls": [{ "url": "https://app.example.com/dashboard" }],"cookies": [{ "name": "session", "value": "<session cookie value>" }],"headers": { "Authorization": "Bearer <token>" }}
- Cookies without
domainare set for the host of each captured URL only. Add"domain": ".example.com"(and optionally"path") to cover a domain and its subdomains. Cookies without a name or a text value are ignored, with a warning that gives their number, not their content. - HTTP headers are sent only to the host of each captured URL (
example.comandwww.example.comcount as the same host), so anAuthorizationheader or API key never reaches third-party scripts, images, fonts, analytics or a redirect to another domain. For that, page requests are routed through the browser and service workers are blocked. Turn on Send headers to every domain only when the site loads protected resources from other hosts you trust. - Sitemap downloads follow the same rules, with the sitemap URL you entered as the target host.
- Pages found in a sitemap get the HTTP headers only when they are on the host of the sitemap URL you entered (unless Send headers to every domain is on), and cookies without
domainonly when they are on that host or on the host of a URL you listed yourself, even with Send headers to every domain. So a sitemap that lists pages on another site never hands that site your credentials. Cookies with an explicitdomainkeep their own scope, and pages you list directly in URLs keep the rules above. - Both fields are stored encrypted, and their values are never written to the log or the dataset. Header names must be valid HTTP header names and values single-line text, otherwise the run stops before loading any page.
Only capture pages you are allowed to access, and prefer a dedicated account or a short-lived token.
What data do you get?
| Fields | Meaning |
|---|---|
url, loadedUrl, title, httpStatus | Input page and navigation metadata |
status, errorMessage | success, failed or skipped (cost limit reached) and the reason |
screenshotUrl, screenshotKey | Download link and key-value-store record |
format, device, fullPage | Capture options used |
width, height, fileSizeBytes | Encoded image dimensions and file size; PDF dimensions are null |
truncated | Whether the long-page image was cut at the height limit |
cookieBannerDismissed | Whether the consent handler clicked a button |
partUrls | All images of a long page split into several parts |
changed, changePercent, textChanged | Change monitoring results (null without monitoring or on the first run) |
textChanges | Lines of text added and removed since the previous run |
diffImageUrl, diffImageNote | Screenshot with changes highlighted, or why none was made |
previousCapturedAt, previousScreenshotUrl | Previous capture of the page when monitoring |
priceChanged, previousPrice, priceChangePercent | Structured price compared with the previous run (price monitoring) |
availabilityChanged, previousAvailability | Structured stock status compared with the previous run |
text, textTruncated | Visible text (plain or Markdown) when text extraction is on |
metadata | Description, canonical URL, language, h1, Open Graph tags |
structuredData | JSON-LD blocks with a Product (price, availability) and Article summary |
capturedAt | Capture timestamp |
Example output
Illustrative excerpts with a placeholder file URL; real links are in your run's dataset.
[{"url": "https://example.com/","loadedUrl": "https://example.com/","status": "success","httpStatus": 200,"title": "Example page","screenshotUrl": "https://api.apify.com/v2/key-value-stores/aBcDeFgHiJkLmNoPq/records/screenshot-0123456789abcdef0123.png","format": "png","fullPage": false,"truncated": false,"cookieBannerDismissed": false,"device": "custom","width": 1280,"height": 800,"fileSizeBytes": 100000,"errorMessage": null},{"url": "https://example.invalid/","loadedUrl": null,"status": "failed","httpStatus": null,"screenshotUrl": null,"format": "png","width": null,"height": null,"errorMessage": "Navigation failed: the host could not be resolved."}]
How much does it cost to capture and monitor websites?
One simple price, every feature included: $6 per 1,000 pages checked ($0.006 per page). Apify's free plan includes $5 of monthly credit: about 800 pages a month for free. The Pricing tab shows the current price of the page event.
Run start: each run also has a small start fee of $0.001 per GB of memory, charged automatically by Apify: $0.004 per run at the default 4 GB. It covers starting the container and the browser, so a run that finds nothing costs you less than half a cent.
| What happens to a page | Charged? |
|---|---|
Captured (image or PDF saved, success item written) | Yes, one page |
| Found unchanged in monitoring, even when Only changed pages hides it | Yes, one page |
| Failed (blocked, not found, timed out, unreachable) | No |
| Skipped because the maximum cost per run was reached | No |
The unit is one page checked on one device: a URL captured on desktop and mobile counts as two pages. A page found unchanged since the previous run is still a check, so it counts even when Only changed pages leaves it out of the dataset. Everything else is included at no extra charge: full-page captures, split long pages, PDF, page text or Markdown, metadata, structured data, change detection with diff images, text, price and stock changes, notifications and sitemap reading.
Example: monitoring 500 product pages every day costs 500 × $0.006 = $3 per day, whether 2 or 200 of them changed. Set a maximum cost per run to cap a run: pages the remaining budget cannot pay for are not loaded and are reported as skipped. Proxies are off by default. Apify compute and Apify Proxy traffic are covered by the page price: you pay for pages, not for servers. With residential proxies, the page and its data requests go through the proxy, so the site sees a residential visitor from the country you chose, while static files (scripts, styles, images, fonts, videos), which content delivery networks serve the same to everyone, are downloaded directly. A file refused that way is fetched through the proxy instead.
Long-page image captures are capped near 60,000 image pixels in height, adjusted for the device pixel ratio. fullPage: true with truncated: true means the requested full-page image was cropped. Mobile image width can vary with page layout and pixel density; use the actual output dimensions. PDF exports retain rendered text when the source page contains text, but they do not OCR text embedded in images.
Troubleshooting
A page timed out? Check the error, try DOMContentLoaded instead of network idle, or wait for a specific visible element. With Page loaded, a page whose load event is held back by a slow third-party resource is captured after 15 seconds, once its fonts and visible images are ready. Increasing retries will not fix an invalid hostname.
A cookie banner remains? Set its selector in Hide elements, or inspect the page for a suitable selector. Automatic dismissal cannot handle every consent system or closed shadow root.
A site answers 403 or blocks the page? Some sites block cloud data-center IP addresses. The URL gets a failed item with the reason and the rest of the batch continues. Definitive answers (HTTP 401, 403, 404, 410 and 451) are not retried, since the site would give the same answer again; failed pages are free. Retry those URLs with Proxy configuration, for example residential proxies (Apify Proxy is a paid feature).
Duplicate URLs? Each distinct normalized URL is captured once. Invalid URLs are skipped and logged; if none are valid, the run fails. When every valid URL fails (for example all blocked), the run still succeeds, and the status message and SUMMARY record explain it.
Every monitored page is reported as changed? Dynamic content such as clocks, ads or carousels changes between runs. Open diffImageUrl to see what changed, then list those areas in Ignore regions, hide them with Hide elements, capture a stable section with Capture element, or raise Change threshold.
A sitemap gives no pages? Check the log line Sitemaps: … read, … pages listed, … selected. If pages are listed but none selected, your include pattern does not match the URLs as the sitemap writes them. If no sitemap could be read, the site may block direct downloads; enter the page URLs instead.
A cookie banner appears after a few seconds? Set Extra delay: the Actor tries to close the banner again once the delay is over.
Automate with n8n, Make, Zapier, Clay and AI agents (MCP)
Every run can be started from another tool, and its results read back as JSON, CSV or Excel. The Actor ID is dgn-lab/website-screenshot-batch (dgn-lab~website-screenshot-batch in API URLs). Get an API token in Apify Console > Settings > API & Integrations and keep it in your tool's credential store: never paste it into shared workflows, public files or prompts.
Apify API: run and get the results in one request
curl -X POST "https://api.apify.com/v2/actors/dgn-lab~website-screenshot-batch/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>&format=json&maxTotalChargeUsd=5" \-H "Content-Type: application/json" \-d '{"startUrls": [{"url": "https://example.com"}], "format": "png", "extractText": true, "textFormat": "markdown"}'
The request body is the Actor input (same fields as the Input tab) and the response is the dataset items. Use format=csv or format=xlsx for a file, and maxTotalChargeUsd to cap what one run can cost. This synchronous endpoint answers with HTTP 408 when the run lasts more than 300 seconds. Each page is loaded in a real browser, so keep synchronous calls to a handful of URLs. For longer runs, start the run with POST https://api.apify.com/v2/actors/dgn-lab~website-screenshot-batch/runs and read GET https://api.apify.com/v2/datasets/<defaultDatasetId>/items once it has finished, or let a webhook tell you (below). The API tab shows the same calls in JavaScript, Python and cURL.
n8n
- Install the official Apify node: on n8n Cloud, search Apify in the nodes panel; self-hosted, go to Settings > Community Nodes and install
@apify/n8n-nodes-apify. - Add the node with the operation Run an Actor and get dataset, select
dgn-lab/website-screenshot-batchand paste your input JSON in Custom input. - Use
screenshotUrl,diffImageUrlortextin the next nodes: post changed pages to Slack, store Markdown in a vector database, or add screenshot links to Google Sheets.
To process scheduled runs instead, start the workflow with the On new Apify Event trigger on this Actor (or on your saved task). In an AI Agent workflow, add the Apify Tool so the agent can run the Actor itself. Guide: Apify n8n integration.
Make
Add the Apify app, module Run an Actor with Run synchronously set to Yes, then Get Dataset Items with the run's default dataset ID, then for example Google Sheets Bulk Add Rows. Make limits how long a synchronous module can wait; for longer runs use the Watch Actor Runs trigger and start the Actor from a schedule. Guide: Apify Make integration.
Zapier
Zapier waits at most 30 seconds for a synchronous Run Actor action, so for this Actor use the trigger Finished Actor run (or Finished task run for a saved task), then the search Fetch dataset items, then your next app (Google Sheets, a CRM, Slack, Gmail). Start the runs from an Apify schedule or from another Zap with Run Actor (asynchronous). Guide: Apify Zapier integration.
Clay
There is no Apify app inside Clay; use Clay's own HTTP API integration with the synchronous endpoint above (method POST, token in the URL from your Clay secrets). For example, one page per row: {"startUrls": [{"url": "{{Website}}"}], "extractText": true, "textFormat": "markdown", "extractMetadata": true}, with your column inserted in place of {{Website}}, then map screenshotUrl, title, metadata and text.
AI agents and MCP clients
Add the Apify MCP server to Claude, ChatGPT, Cursor, VS Code or any MCP client with this URL, which loads only this Actor as a tool:
https://mcp.apify.com?tools=dgn-lab/website-screenshot-batch
On the first connection your browser opens to sign in to Apify (OAuth), so no token is written in the client configuration. The agent can then run the Actor and read its dataset (get-dataset-items). With the Apify CLI, apify mcp install <client> writes the configuration for you.
Schedules and webhooks
Save your input as a task, then create a schedule in Apify Console > Schedules with a cron expression and time zone. To push results to your own system, open the Actor's or task's Integrations tab and add a webhook on the ACTOR.RUN.SUCCEEDED event: Apify sends a POST request with the run details, including defaultDatasetId, to your URL. See webhooks.
FAQ, disclaimer and support
Can it monitor a website for changes and send alerts?
Yes. Turn on Monitor changes, schedule the Actor or a task, and set a Notification webhook URL for Slack, Discord, Telegram or any endpoint. Each run compares every page with its previous capture. See Monitor pages for changes.
Can I convert a web page to Markdown or PDF?
Yes. Extract page text with Text format Markdown returns headings, lists, links and tables as Markdown; Image format PDF saves the page as a PDF. Both can run in the same batch as screenshots.
How do I screenshot a whole website?
Enter its sitemap (for example https://example.com/sitemap.xml) in URLs: every page listed is captured, sitemap indexes and .xml.gz files included, and you can keep or drop pages with include and exclude patterns. See Capture pages from a sitemap.
How do I take desktop and mobile screenshots at the same time?
Select desktop and mobile presets in Several devices: each URL is captured once per device, and each capture counts as one page.
How do I track competitor prices?
Add the competitor product pages, turn on Monitor changes and schedule the task. Product price and availability published as schema.org data are compared from run to run, and the alert says which page changed and how. See Monitor prices and stock.
How much does a website screenshot cost?
$0.006 per page ($6 per 1,000), with full-page capture, PDF, Markdown, change detection, diff images and alerts included. A failed page costs nothing.
Can it capture pages behind a login?
Yes, with session Cookies or HTTP headers, stored encrypted and sent only to the captured site by default. See Capture pages behind a login.
Is it legal to screenshot websites?
Capture only pages you are allowed to access. Screenshots and extracted text contain whatever the page shows, which can include personal data or copyrighted content. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.
Support
Use the API tab for code examples. For a bug, open the Issues tab with the input and run ID. Remove credentials, cookies and headers from anything you share.