Skip to main content
Changedetection.io supports over 100 notification services through the powerful Apprise library. Configure notifications globally or per-watch with custom templates using Jinja2.

Supported Services

Changedetection.io supports:
  • Chat: Discord, Slack, Mattermost, Rocket.Chat, Telegram, Matrix
  • Email: SMTP, Gmail, Office365, Mailgun, SendGrid
  • Collaboration: Microsoft Teams, Google Chat, Flock, Gitter
  • Incident Management: PagerDuty, Opsgenie, VictorOps
  • Custom: Webhooks (JSON/XML), Syslog, MQTT
  • And 100+ more services

Apprise URL Syntax

Apprise uses URL-based configuration. Each service has a specific URL format.

Discord

discord://webhook_id/webhook_token
string
Discord webhook notificationSteps to get webhook URL:
  1. In Discord, go to Server Settings β†’ Integrations β†’ Webhooks
  2. Click β€œNew Webhook” or edit existing
  3. Copy the webhook URL: https://discord.com/api/webhooks/{id}/{token}
  4. Extract the ID and token, format as: discord://{id}/{token}
Example:
discord://1234567890/AbCdEfGhIjKlMnOpQrStUvWxYz

Slack

slack://tokenA/tokenB/tokenC/
string
Slack webhook notificationSteps to get webhook URL:
  1. Go to https://api.slack.com/apps
  2. Create a new app or select existing
  3. Enable β€œIncoming Webhooks”
  4. Add webhook to workspace
  5. Copy webhook URL: https://hooks.slack.com/services/T.../B.../X...
  6. Extract tokens after /services/: slack://T.../B.../X...
Example:
slack://T1234567/B1234567/XXXXXXXXXXXX

Email (SMTP)

mailto://user:pass@example.com?to=recipient@example.com
string
Email notification via SMTPFormat:
mailto://[user]:[password]@[hostname]:[port]?to=[recipient]
Example with Gmail:
mailto://myuser:mypassword@smtp.gmail.com:587?to=alerts@example.com
Example with Office365:
mailto://user:pass@smtp.office365.com:587?to=recipient@example.com

Office365

o365://TenantID:AccountEmail/ClientID/ClientSecret/TargetEmail
string
Office365 email using Microsoft Graph APIFormat:
o365://[TenantID]:[AccountEmail]/[ClientID]/[ClientSecret]/[TargetEmail]
Example:
o365://abc123:sender@company.com/client-id-here/secret-here/recipient@company.com

Microsoft Teams

msteams://TokenA/TokenB/TokenC/
string
Microsoft Teams webhook notificationSteps to get webhook URL:
  1. In Teams, go to the channel where you want notifications
  2. Click ”⋯” β†’ β€œConnectors” β†’ β€œIncoming Webhook”
  3. Configure webhook and copy URL
  4. Extract tokens from URL
Example:
msteams://TokenA/TokenB/TokenC/

Google Chat

gchat://workspace/key/token
string
Google Chat webhook notificationExample:
gchat://myworkspace/AIza...../token-here

Telegram

tgram://bottoken/ChatID
string
Telegram bot notificationExample:
tgram://123456789:ABCdefGHIjklMNOpqrsTUVwxyz/-123456789

Rocket.Chat

rocket://user:password@hostname/#Channel
string
Rocket.Chat webhook notificationExample:
rocket://myuser:mypass@chat.example.com/#alerts

Custom JSON Webhook

json://someserver.com/custom-api
string
Custom JSON POST webhookExample:
json://api.example.com/webhook
jsons://api.example.com/secure-webhook
The notification data will be POSTed as JSON to your endpoint.

Syslog

syslog://
string
Send notifications to local syslogExample:
syslog://
syslog://remote-server:514

Global vs Per-Watch Notifications

Global Notifications

Set default notification URLs that apply to all watches:
  1. Go to Settings (gear icon)
  2. Navigate to Notifications tab
  3. Enter notification URLs (one per line)
  4. Save settings
Example global configuration:
discord://1234567890/AbCdEfGhIjKlMnOpQrStUvWxYz
slack://T1234567/B1234567/XXXXXXXXXXXX
mailto://alerts:pass@smtp.gmail.com?to=team@example.com

Per-Watch Notifications

Override global settings for specific watches:
  1. Edit a watch
  2. Go to Notifications tab
  3. Enter notification URLs (one per line)
  4. Enable/disable specific notifications
  5. Save watch
Per-watch notifications override global notifications. If a watch has notification URLs configured, global notifications will not be sent.

Tag-Based Notifications

Configure notifications at the tag level:
  1. Go to Tags page
  2. Edit a tag
  3. Configure notification URLs
  4. All watches with this tag inherit these notifications
Priority order:
Individual Watch Settings > Tag Settings > Global Settings

Notification Templates (Jinja2)

Customize notification content using Jinja2 templates with access to watch data, diffs, and timestamps.

Available Template Variables

watch_url
string
The URL being monitoredExample:
{{ watch_url }}
watch_title
string
The title/name of the watchExample:
{{ watch_title }}
watch_uuid
string
Unique identifier for the watchExample:
{{ watch_uuid }}
watch_tag
string
Tags assigned to the watch
base_url
string
Your changedetection.io instance URL (set via BASE_URL env variable)Example:
Edit: {{ base_url }}/edit/{{ watch_uuid }}
diff
string
Diff showing changes (with +/- prefixes)Example:
{{ diff }}
With parameters:
{{ diff(lines=5) }}
{{ diff(added_only=true) }}
{{ diff(removed_only=true) }}
{{ diff(context=3) }}
diff_clean
string
Diff without +/- prefixes
diff_added
string
Only added linesExample:
{{ diff_added(lines=10) }}
diff_removed
string
Only removed lines
diff_full
string
Full diff including unchanged lines
diff_patch
string
Diff in unified patch format
current_snapshot
string
Current version of the content
prev_snapshot
string
Previous version of the content
change_datetime
string
Timestamp when change was detectedExample:
{{ change_datetime }}
{{ change_datetime(format='%Y-%m-%d') }}
{{ change_datetime(format='%A') }}
triggered_text
string
Text that matched trigger filters
preview_url
string
URL to preview the changes in changedetection.io
diff_url
string
Direct URL to the diff view
screenshot
string
Base64-encoded screenshot (if enabled)

Custom Notification Title

Edit the notification title in Settings β†’ Notifications: Default title:
ChangeDetection.io Notification - {{ watch_url }}
Custom title examples:
πŸ”” {{ watch_title }} has changed!

Price Alert: {{ watch_title }}

{{ watch_tag }}: Change detected on {{ watch_url }}

Custom Notification Body

Edit the notification body in Settings β†’ Notifications: Default body:
Changed: {{ watch_url }}

{{ diff }}
Custom body examples: Example 1: Compact format
URL: {{ watch_url }}
Changed: {{ change_datetime(format='%Y-%m-%d %H:%M:%S') }}

Changes:
{{ diff(lines=10) }}

View: {{ preview_url }}
Example 2: Added lines only
πŸ†• New content detected on {{ watch_title }}

{{ diff_added_clean(lines=15) }}

Full details: {{ base_url }}/preview/{{ watch_uuid }}
Example 3: Rich formatting
**Website:** {{ watch_url }}
**Title:** {{ watch_title }}
**When:** {{ change_datetime }}
**Tags:** {{ watch_tag }}

## What changed:
{{ diff(lines=20, context=2) }}

[View full changes]({{ diff_url }})
[Edit watch]({{ base_url }}/edit/{{ watch_uuid }})
Example 4: Price monitoring
πŸ’° Price update for {{ watch_title }}

Previous price: {{ prev_snapshot }}
Current price: {{ current_snapshot }}

{{ diff_clean }}

Check now: {{ watch_url }}

Conditional Notifications

Use Jinja2 conditionals for advanced logic:
{% if diff_added %}
πŸ†• New content added:
{{ diff_added(lines=5) }}
{% endif %}

{% if diff_removed %}
❌ Content removed:
{{ diff_removed(lines=5) }}
{% endif %}

{% if watch_tag == 'urgent' %}
🚨 URGENT: Immediate attention required
{% endif %}

Notification Formats

Changedetection.io supports multiple notification formats:
notification_format
string
Format for notification contentValues:
  • text - Plain text (default)
  • markdown - Markdown formatting
  • html - HTML formatting
Set in Settings β†’ Notifications β†’ Format dropdown

Markdown Format

Use markdown for rich formatting:
## Change Detected: {{ watch_title }}

**URL:** {{ watch_url }}
**Time:** {{ change_datetime }}

### Changes:
{{ diff(lines=10) }}

[View Details]({{ preview_url }})

HTML Format

Use HTML for email notifications:
<h2>Change Detected</h2>
<p><strong>URL:</strong> <a href="{{ watch_url }}">{{ watch_title }}</a></p>
<p><strong>When:</strong> {{ change_datetime }}</p>
<h3>Changes:</h3>
<pre>{{ diff(lines=10) }}</pre>
<p><a href="{{ preview_url }}">View Full Details</a></p>

Muting Notifications

Mute Individual Watch

  1. Edit watch
  2. Go to Notifications tab
  3. Check Mute notifications for this watch
  4. Save

Mute All Notifications

  1. Go to Settings
  2. Enable Mute all notifications toggle
  3. Save
The all_muted setting overrides all watch-level and tag-level notification settings.

Mute by Tag

  1. Edit tag
  2. Enable Mute notifications for tag
  3. All watches with this tag will have notifications muted

Notification Screenshots

Include screenshots in notifications:
  1. Edit watch
  2. Go to Notifications tab
  3. Enable Include screenshot in notification
  4. Save
Screenshots require a browser-based fetcher (Playwright/Puppeteer) and increase notification size.

Testing Notifications

Test Global Notifications

  1. Go to Settings β†’ Notifications
  2. Click Send test notification
  3. Check your notification service for the test message

Test Watch Notifications

  1. Edit watch
  2. Go to Notifications tab
  3. Click Send test notification
  4. Verify notification received

Troubleshooting

Notifications Not Sending

  1. Check notification URLs: Verify the Apprise URL format is correct
  2. Test connectivity: Ensure changedetection.io can reach the notification service
  3. Check logs: Look for errors in Docker logs: docker logs changedetection
  4. Verify watch isn’t muted: Check watch and global mute settings

Template Errors

If Jinja2 templates fail:
  1. Syntax errors: Check for missing }}, %}, or quotes
  2. Undefined variables: Ensure template variables exist (e.g., watch_title may be empty)
  3. Test with simple template: Start with {{ watch_url }} and add complexity

Discord/Slack Not Receiving

  1. Webhook permissions: Verify webhook has permission to post
  2. Rate limits: Check if you’re hitting API rate limits
  3. URL format: Double-check Discord/Slack webhook URL format

Email Notifications Failing

  1. SMTP settings: Verify hostname, port, username, password
  2. Authentication: Use app-specific passwords for Gmail
  3. TLS/SSL: Try different ports (587 for STARTTLS, 465 for SSL)
  4. NO_PROXY: Add email server to NO_PROXY environment variable

Best Practices

  1. Test notifications before deploying watches
  2. Use templates to reduce notification fatigue
  3. Set NO_PROXY to exclude notification services from proxy routing
  4. Use per-watch notifications for critical watches
  5. Limit diff size in templates with diff(lines=10)
  6. Monitor notification count to avoid overwhelming channels
  7. Use tags to organize notification routing

Example Configurations

Multi-Channel Setup

# Critical alerts to PagerDuty and Teams
pagerduty://integration-key-here
msteams://TokenA/TokenB/TokenC/

# All changes to Discord
discord://1234567890/AbCdEfGhIjKlMnOpQrStUvWxYz

# Daily digest via email
mailto://alerts:pass@smtp.gmail.com?to=team@example.com

Custom Webhook with Template

Notification URL:
json://api.example.com/changedetection-webhook
Notification Body:
{
  "event": "page_changed",
  "url": "{{ watch_url }}",
  "title": "{{ watch_title }}",
  "timestamp": "{{ change_datetime(format='%Y-%m-%dT%H:%M:%SZ') }}",
  "diff_summary": "{{ diff(lines=3) }}",
  "view_url": "{{ preview_url }}"
}