You need to know when a web page changes. Maybe it is a competitor's pricing page, a regulatory document, a product listing page, or a documentation site your application depends on. The question is whether you build the monitoring infrastructure yourself or use an API that handles it for you.
This guide covers everything a developer needs to know about website change monitoring APIs: how they work, how to integrate them, and how to build automated workflows on top of change detection.
What does a website change monitoring API do?
A website change monitoring API handles four things you would otherwise build yourself:
- Scheduled fetching - Opens pages on a configurable schedule using a real browser (handling JavaScript rendering, dynamic content, and bot protection)
- Change detection - Compares each fetch with the previous one, identifying what specifically changed
- Diff generation - Produces structured diffs in multiple formats (text, HTML, markdown, visual screenshots)
- Event delivery - Sends webhooks, emails, or push notifications when changes are detected
Without a monitoring API, you are writing cron jobs, managing headless browsers, storing snapshots, building comparison logic, and wiring up notifications. That is a substantial engineering investment for what should be a utility.
Setting Up Your First Monitor
Most monitoring APIs follow a similar pattern. Here is how it works with PageCrawl's REST API:

1. Create a monitor:
curl -X POST "https://pagecrawl.io/api/track-simple" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://competitor.com/pricing",
"tracking_mode": "fullpage",
"frequency": 60
}'2. Set up a webhook:
curl -X POST "https://pagecrawl.io/api/hooks" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"target_url": "https://your-app.com/webhooks/page-change",
"match_type": "all",
"events": ["change_detected"]
}'3. Process incoming changes:
@app.route("/webhooks/page-change", methods=["POST"])
def handle_change():
data = request.json
print(f"Page changed: {data['title']}")
print(f"AI summary: {data.get('ai_summary')}")
print(f"Diff: {data.get('markdown_difference')}")
# Your application logic here
return "", 200That is the entire setup. The API handles scheduling, browser rendering, comparison, and delivery.
Which tracking mode should you use?
Default to fullpage and switch only when the content type demands it: price for product pages, content_only for editorial, feed for repeating listings, specific_text when one element is all that matters. A pricing page needs different handling than a terms of service document or an RSS feed.
| Mode | Best for | What it tracks |
|---|---|---|
fullpage |
General pages, ToS, policies | All visible text |
content_only |
News, blogs, articles | Main content (strips navigation and sidebars) |
reader |
Editorial content | Reader-mode extracted text |
price |
E-commerce, product pages | Auto-detected prices and availability |
specific_text |
Any page | Text of a specific CSS/XPath element |
specific_number |
Dashboards, stats | Numeric value from a specific element |
feed |
Job boards, listings | Repeating items (additions, removals, changes) |
seo |
Marketing, SEO | Title, meta, canonical, robots, OG tags |
For most use cases, fullpage is the right default. Use price for e-commerce pages, content_only for editorial content, and specific_text when you only care about one element on the page. The full catalogue, including file and document types, is listed under available tracked element types.
Webhook Payload Structure
When a change is detected, the webhook delivers a JSON payload with structured data about the change. You can customize which fields are included.
{
"id": 12345,
"title": "Competitor Pricing Page",
"status": "ok",
"changed_at": "2026-05-04T14:30:00Z",
"contents": "Pro plan: $59/month...",
"difference": 8,
"human_difference": "Text difference of 8%",
"ai_summary": "The Pro plan price increased from $49/mo to $59/mo. The Enterprise plan now includes SSO.",
"ai_priority_score": 85,
"markdown_difference": "- Pro plan: $49/month\n+ Pro plan: $59/month",
"page": {
"id": 100,
"name": "Competitor Pricing Page",
"url": "https://competitor.com/pricing",
"slug": "competitor-pricing"
}
}Key fields for developers:
markdown_difference- Machine-parseable diff showing additions and removalsai_summary- Natural language summary of what changed (generated automatically)ai_priority_score- 0-100 importance score (higher = more significant change)contents- Current value of the tracked elementpage_screenshot_image- Signed URL to a full-page screenshot
What diff formats can you pull from the API?
Every detected change is available as a PNG image, rendered HTML, markdown, or a unified patch, so you can embed it in a report, render it in your own UI, feed it to a model, or apply it as a patch. Beyond webhooks, you can retrieve diffs on demand in multiple formats:
| Format | Endpoint | Use case |
|---|---|---|
| PNG image | GET /api/pages/{id}/checks/{checkId}/diff.png |
Embed in reports, emails |
| HTML | GET /api/pages/{id}/checks/{checkId}/diff.html |
Render in web UI |
| Markdown | GET /api/pages/{id}/checks/{checkId}/diff.markdown |
Feed to LLMs, log in text |
| Patch | GET /api/pages/{id}/checks/{checkId}/diff.patch |
Apply as unified diff |
Notification Rules
Not every change deserves an alert. Use notification rules to filter which changes trigger webhooks:
{
"rules_enabled": true,
"rules": [
{"type": "contains", "value": "price"},
{"type": "text_difference", "value": 5}
],
"rules_and": false
}Available rule types include contains, added, removed, gt, lt, increased, decreased, and more. See the full API reference for all options, and notification conditions and filters for the equivalent controls in the dashboard.
Common Integration Patterns
Database logging
Store every detected change in your own database for historical analysis:
@app.route("/webhooks/page-change", methods=["POST"])
def log_change():
data = request.json
db.execute(
"INSERT INTO page_changes (monitor_id, url, changed_at, summary, diff, priority) VALUES (?, ?, ?, ?, ?, ?)",
[data['page']['id'], data['page']['url'], data['changed_at'],
data.get('ai_summary'), data.get('markdown_difference'),
data.get('ai_priority_score')]
)
return "", 200Slack alerting with priority filtering
Only send high-priority changes to Slack:
@app.route("/webhooks/page-change", methods=["POST"])
def alert_slack():
data = request.json
priority = data.get("ai_priority_score", 0)
if priority < 50:
return "", 200 # Skip low-priority noise
requests.post(SLACK_WEBHOOK, json={
"text": f"*{data['title']}* changed (priority: {priority}/100)\n{data.get('ai_summary', 'No summary')}"
})
return "", 200Trigger CI/CD on documentation changes
Re-deploy when your documentation source changes, using a repository dispatch event from the GitHub REST API:
@app.route("/webhooks/page-change", methods=["POST"])
def trigger_rebuild():
data = request.json
# Trigger GitHub Actions workflow
requests.post(
f"https://api.github.com/repos/{REPO}/dispatches",
headers={"Authorization": f"token {GITHUB_TOKEN}"},
json={"event_type": "docs-changed", "client_payload": {"url": data['page']['url']}}
)
return "", 200MCP Server for AI Assistants
If you use Claude, ChatGPT, or Cursor, the PageCrawl MCP server, which implements the open Model Context Protocol, lets AI assistants manage monitors through conversation:
- "Monitor docs.example.com and alert me when the API reference changes"
- "What changed across all my monitors today?"
- "Show me the diff for the last change on the pricing page"
This is particularly useful for developers who want to set up API and documentation change monitoring without leaving their IDE.
Getting Started
Start with the API quick-start guide to create your first monitor and webhook in under a minute. The interactive API reference has all endpoints with schemas and example responses.
PageCrawl was built with developers in mind from day one, with a full REST API, customizable webhooks, an MCP server for AI assistants, and a downloadable OpenAPI spec. The free tier includes 6 monitors with AI summaries and webhooks, so you can build and test your integration before committing to a paid plan.




