Website Change Monitor: Text Diff, Markdown & Screenshot
Pricing
from $1.20 / 1,000 page checkeds
Website Change Monitor: Text Diff, Markdown & Screenshot
Website change monitor for a list of URLs: see exactly what changed since the last run as added and removed lines of page text, plus a content hash, clean Markdown and a screenshot per page. Schedule it to watch prices or docs. From $1.20 per 1,000 pages ($2 on the Free plan, less on paid plans).
Pricing
from $1.20 / 1,000 page checkeds
Rating
0.0
(0)
Developer
Otama Labs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 hours ago
Last modified
Categories
Share
Website change monitor for anyone who needs to know when a web page changes (competitor prices, product docs, terms of service, job or tender pages, sources of a RAG index): give it a list of URLs and get one row per page with what changed since the last run as added and removed lines of text, plus a content hash, the clean page text as Markdown and a screenshot. Schedule it and you have a change feed you can read in a spreadsheet, a webhook, an AI agent or a script.
Most screenshot tools give you a picture and leave the comparing to you. This Actor renders each page in a real Chromium browser, turns the main content into clean Markdown, and compares it with the version it saw last time, so a diff like -Starter: $10 / +Starter: $12 lands straight in your dataset.
What you get for each page
A real row (the test page returns a new random id on every load, so the second run reports a change):
{"url": "https://httpbin.org/uuid","finalUrl": "https://httpbin.org/uuid","httpStatus": 200,"status": "changed","checkedAt": "2026-10-20T06:31:49.259881+00:00","previousCheckedAt": "2026-10-20T06:31:44.787828+00:00","contentHash": "f117a982ef6b9cbb9b6dc869ea08cd851f68d655d483d09b7d1f00053992f435","addedLines": 1,"removedLines": 1,"diff": ["-\"uuid\": \"8342f2be-c43b-4f6f-a302-42b7607a2c94\"","+\"uuid\": \"47b97d11-309a-493a-bb9a-973d21035e7b\""],"wordCount": 6,"screenshotUrl": null,"screenshotError": null,"markdown": "```\n{\n\"uuid\": \"47b97d11-309a-493a-bb9a-973d21035e7b\"\n}\n```","error": null}
| Field | Meaning |
|---|---|
status | new (first check under this monitor name), changed, unchanged or error |
diff | Changed lines of the page text: + added, - removed (up to Max diff lines) |
addedLines, removedLines | Complete counts, even when the diff is cut |
contentHash | SHA-256 of the page text. Same text, same hash |
markdown | Main content as Markdown: headings, lists, links, tables. Scripts, styles and images are left out |
screenshotUrl | JPEG of the first screen (1280×800) or the full page, stored in the run's key-value store |
screenshotError | Set when a full-page screenshot was too slow (then the first screen is saved) or failed; the text check still counts |
title, httpStatus, finalUrl | Page title, HTTP status, address after redirects |
error | Why a page could not be checked (blocked address, HTTP 404, timeout...). These rows are free |
The run's key-value store also has a SUMMARY record: pages checked, changed, new, unchanged and errors.
How to use it in 5 minutes
- Click Try for free. The form is filled with two example pages; press Start. Both come back as
newin a few seconds. - Replace them with the pages you care about and pick a Monitor name, for example
competitor-pricing. - Run it once to store the first version, then add a Schedule (daily or hourly) with the same input.
- Every later run returns
changedrows with the diff. Filter the dataset onstatus = changed, or connect an integration (email, Slack, webhook) that fires when the run finishes.
Tip: if a page shows a clock, a visitor counter or rotating offers, put their CSS selectors in Ignore these elements, or compare only the part you care about with Compare only this part of the page (e.g. #pricing). Otherwise every run reports a change.
Input
| Field | Default | Description |
|---|---|---|
urls | (required) | Public http/https pages, up to 100 per run |
monitorName | default | The memory the next run compares against. Same name for the same watch list |
contentSelector | main content | CSS selector of the part to compare |
ignoreSelectors | none | CSS selectors removed before comparing |
maxDiffLines | 200 | Diff lines kept per page (0 to 5,000) |
screenshot | viewport | viewport, fullPage (cut at 16,000 px) or none |
includeMarkdown | true | Add the page text to each row |
waitSeconds | 0 | Extra wait after load for late content (0 to 15) |
Pricing
Pay per event: $2 per 1,000 pages checked ($0.002 per page) on the Free plan, lower on paid Apify plans (Bronze $0.0018, Silver $0.0015, Gold and above $0.0012), plus a tiny start fee of $0.00005 per GB of memory per run (the default 1 GB counts as one). Platform usage is included. Pages that fail (blocked, 4xx/5xx, timeout) are not charged.
Example: watching 50 pages once a day for 30 days is 1,500 checks = $3.00 on the Free plan.
What it does not do
- No pages behind a login, no form filling, no CAPTCHA solving. Bot-protected pages may return a challenge page instead of the content; such a page is still compared as it was rendered.
- Public pages only. URLs that point to localhost, private networks (10.x, 192.168.x...), link-local or cloud metadata addresses are refused, also when a public page redirects there. This is a best-effort guard based on the DNS answer at check time, not a network firewall.
- No notifications of its own. Use Apify integrations or webhooks on the finished run.
- The comparison is on text, not on pixels: a changed image or color without a text change is not reported.
- The stored version is the first 300,000 characters of a page's text; a change beyond that point is caught by the hash but not shown in the diff.
- Two pages are loaded at once. Loading a page may take up to 30 seconds, plus up to 5 seconds for network activity to settle, your extra wait and the screenshot. Very large rows are cut: Markdown at 1,000,000 characters and each diff line at 2,000.
Please respect each site's terms of use when choosing pages to monitor.
FAQ
Where is the previous version stored? In a named key-value store page-snapshot-state in your own Apify account, one record per page and monitor name. Nobody else can read it; delete it to start over.
How do I call it from code, Make, n8n or Zapier? Run the Actor with the Apify API or the official Apify apps for Make, n8n and Zapier, then read the dataset items. With the Apify MCP server, AI agents can call it as a tool. LangChain and LlamaIndex have Apify loaders for the dataset.
Why did a page change although nothing visible changed? Dynamic text (dates, counters, recommendations) is part of the page text. Exclude it with Ignore these elements or narrow the comparison with Compare only this part of the page.
Can I get only the changed pages? Read the dataset items and keep the rows with status == "changed". All checked pages are returned so you also see unchanged and error rows.
Related Actors by the same author
| Actor | What it does |
|---|---|
| PDF to Markdown | PDF, Word, Excel and PowerPoint to Markdown and RAG chunks |
| PDF OCR | Scanned PDFs and images to text and a searchable PDF |
| ATS Jobs | Job openings from company job boards (Greenhouse, Lever, Ashby and more) |
| RemoteOK & Jobicy Remote Jobs API | Remote job listings from the Remote OK and Jobicy APIs |
For AI Agents
Agents that keep a knowledge base fresh, watch a competitor or follow a changelog need one answer: "did this page change, and how?". This Actor returns exactly that as data (status, diff, addedLines, removedLines), so the agent reads a few lines instead of a whole page. It needs no login, is paid per page through Apify (pay per event) and runs with limited permissions.
Apify MCP server, restricted to this Actor:
{"mcpServers": {"website-change-monitor": {"url": "https://mcp.apify.com?tools=tamatama/website-change-monitor"}}}
Authorize with OAuth in the client, or pass Authorization: Bearer <APIFY_TOKEN>. A check is started through the tool tamatama--website-change-monitor, and get-dataset-items (added by the server) reads the rows when there are many pages. Example input for an agent that follows a changelog:
{ "urls": ["https://example.com/changelog"], "monitorName": "changelog-watch", "screenshot": "none", "includeMarkdown": false }
Keep the same monitorName on every call: that name is what links a run to the previous version. The first call returns status: "new"; later calls return changed or unchanged, and error (with the reason in error) when a page could not be loaded.
OpenAPI: https://api.apify.com/v2/acts/tamatama~website-change-monitor/builds/default/openapi.json. REST: POST https://api.apify.com/v2/acts/tamatama~website-change-monitor/run-sync-get-dataset-items with the JSON input.