Skip to content
CAI
Software that uses CAICheck a score

dgtlmoon/changedetection.io

45.4

Weak · 18 September 2026

63.3k

lines of production code

Python

with JavaScript

1

measurement over time

CAI band scale
CAI lens gauges

What this system is

This system is a self-hosted web page change monitoring application that tracks updates to URLs by capturing screenshots and analyzing text or JSON content. It features a modular architecture supporting multiple processors for visual diffs, price tracking, and restock detection, alongside an extensible plugin system for custom logic. The platform provides a comprehensive web interface for managing watches, configuring complex filtering conditions, and receiving notifications via RSS or third-party services, with recent enhancements including AI-driven change summaries and real-time UI updates.

How it got here

2021–2022 — Modernization and UI overhaul

23 changes.

The project underwent a comprehensive modernization, replacing legacy backend components and build systems with a consolidated Python and Node.js infrastructure. A major focus was placed on a complete UI redesign, introducing a new sidebar navigation, dark mode, and interactive visual diff tools. Concurrently, security was hardened through Pydantic validation and XSS fixes, while new features like LLM integration and browser automation were added.

2023–2025 — Architecture modernization and extensibility

32 changes.

The codebase underwent a major structural overhaul, refactoring the UI into modular Flask blueprints and the processor system into a pluggable architecture to support domain-specific extensions like restock monitoring. This period also introduced advanced content filtering, AI-driven change summaries, and real-time WebSocket updates, significantly enhancing the platform's flexibility and user interface.

2026 — AI integration and localization expansion

24 changes.

The project introduced LLM-based intent evaluation and change summaries, alongside an LLM fallback plugin for price and restock detection, significantly enhancing automated monitoring capabilities. Concurrently, the application expanded its global reach by adding complete translation support for numerous languages and refactoring the data storage for improved reliability.

Features

Add Portuguese (Brazil) translation

Users can now see the application interface in Portuguese (Brazil), with translations covering key areas such as adding new watches, managing backups, and restoring data.

_changedetectionio/translations/pt\BR · high confidence

Add complete Spanish translation (es)

The application now includes a full Spanish language translation, allowing users to view the interface in Spanish. This covers key areas such as adding new watches, managing backups, and restoring data.

changedetectionio/translations/es · high confidence

Add price data follower acceptance/rejection endpoints

A new blueprint provides POST endpoints to accept or reject LD+JSON price tracking for a watch. Accepting sets track\_ldjson\_price\_data to accepted, switches the processor to restock\_diff, clears the watch, and queues it for immediate re-check; rejecting simply marks the watch as rejected. Both actions redirect back to the watchlist.

_changedetectionio/blueprint/price\_data\follower · high confidence

Added British and American English translation files

New translation files for British English (en\_GB) and American English (en\_US) have been added to the application, providing localized UI strings for features such as adding watches, managing backups, and system settings.

_changedetectionio/translations/en\_GB, changedetectionio/translations/en\US · high confidence

Added Extract Data tab for regex-based text extraction from watch history

The interface now includes an 'Extract Data' tab within the diff history view, allowing users to apply regular expressions to extract specific text patterns from all historical watch data. This new tool presents a form where users can input a RegEx pattern, with inline guidance explaining that each captured group will appear as a separate column (with the date always in the first column), and provides a link to test patterns externally.

changedetectionio/processors/templates · high confidence

Added Polish language support

The application now includes a complete Polish translation, allowing users to interact with the interface in their native language. This update covers all major areas including adding new watches, managing backups, and editing watch settings.

changedetectionio/translations/pl · high confidence

Added Traditional Chinese (Taiwan) translation support

The application now includes a new locale for Traditional Chinese (Taiwan), identified as zh\_Hant\_TW. This update adds the initial translation file (messages.po) containing over 5,000 lines of translated strings for the user interface, covering key areas such as adding new watches, browser configuration, backup and restore operations, and general UI elements. Users can now interact with the application in this language variant.

_changedetectionio/translations/zh\_Hant\TW · high confidence

Added Turkish language support

The application now includes a complete Turkish translation, allowing users to interface with the UI in Turkish. This covers key areas such as adding new watches, managing backups, and restoring data.

changedetectionio/translations/tr · high confidence

Added multi-platform favicon and PWA configuration files

The application now includes specific assets to improve appearance across different browsers and devices. A \browserconfig.xml\ file has been added to support Windows tile customization, and a \safari-pinned-tab.svg\ file provides a dedicated icon for Safari pinned tabs. Additionally, a \site.webmanifest\ file defines the Progressive Web App (PWA) settings, including app name, theme colors, and icon sizes for Android Chrome, ensuring the app displays correctly when installed or viewed on mobile devices.

changedetectionio/static/favicons · high confidence

Initial Japanese language support added

Japanese (ja) translations are now available for the application interface, covering key areas such as adding new watches, managing backups, and restoring data. Users can now interact with these specific UI elements in Japanese.

changedetectionio/translations/ja · high confidence

Initial project scaffolding and build configuration

This change introduces the foundational build and development infrastructure for the application. It adds a multi-stage Dockerfile targeting Python 3.11 (Debian Bookworm) with conditional support for Playwright and OpenCV on ARM architectures, alongside a docker-compose.yml for containerized deployment. Development tooling is established via .pre-commit-config.yaml and .ruff.toml for linting and formatting, while MANIFEST.in and setup.py define the package structure for pip distribution. Configuration for internationalization (babel.cfg, setup.cfg) and a .dockerignore file are also included to support the build process.

(repo-wide) · high confidence

Introduce LLM-based intent evaluation and change summaries

Added a new LLM module that enables users to define specific change-detection intents (e.g., 'alert when price drops') and generate AI-powered change summaries. The system uses BM25 relevance trimming to focus on relevant content, supports self-hosted and local endpoints (Ollama, vLLM, LM Studio), and handles complex model behaviors like reasoning blocks and sampling parameter stripping. Users can now configure per-watch or per-group AI settings, override prompts, and disable LLM features entirely via environment variables.

changedetectionio/llm · high confidence

LLM-based fallback for price and restock detection

A new LLM fallback plugin has been added to the restock diff processor to handle product pages where structured metadata (JSON-LD, microdata) fails to provide both price and availability. This plugin sends a cleaned, trimmed version of the page content to a configured LLM to extract structured price and stock status data. The implementation includes configurable content limits (defaulting to 15,000 characters), a local result cache to reduce token usage on unchanged pages, and logic to strip navigation and recommendation noise from the HTML before sending it to the model.

_changedetectionio/processors/restock\diff/plugins · high confidence

Multiprocessing safety hardening and plugin system documentation

The application now enforces the 'spawn' multiprocessing start method by default to prevent deadlocks in multi-threaded environments, ensuring stable operation on Python 3.12+. Additionally, a new plugin system is documented in PLUGIN\_README.md, allowing developers to extend the UI Stats tab via the \ui\_edit\_stats\_extras\ hook. The \auth\_decorator.py\ module introduces strict endpoint-based access control for shared diff pages to prevent unauthorized access to state-changing endpoints.

changedetectionio · high confidence

New API endpoints for managing tags, notifications, and watch imports

The API now includes dedicated endpoints for creating, updating, and deleting tags/groups (Tags.py), managing global notification URLs (Notifications.py), importing watches via query parameters with automatic type conversion and background processing for large lists (Import.py), and searching watches by URL or title (Search.py). These additions are backed by strict OpenAPI schema validation, ensuring that incoming data like tag colors, time schedules, and processor configurations are validated against the spec before being stored.

changedetectionio/api · high confidence

New Add Watch UI with live visual selector and secure snapshot fetching

The 'Add Watch' interface has been refactored to include a live visual selector that fetches a real-time screenshot and element data from the target URL before saving. This new flow uses a dedicated POST-only endpoint to retrieve the snapshot, which includes strict URL validation to prevent SSRF attacks and ensures only browsers capable of rendering previews (supporting screenshots and XPath data) are offered to the user. The system now automatically selects the best available browser for the preview and saves that specific browser choice with the watch, ensuring consistency between the preview and the actual monitoring. Users can now visually select elements on the page to define change detection filters, and if an LLM is configured, they can provide natural language instructions for what changes to watch for.

_changedetectionio/blueprint/add\_watch\ui · high confidence

New Imports page with Distill.io and XLSX support

A new import interface has been added to the application, providing a unified tabbed view for importing watch data. Users can now paste URL lists directly, import configurations from Distill.io via JSON export files, or upload XLSX spreadsheets with custom column mapping for titles, URLs, tags, and recheck intervals. The page also includes a link to the backup restore functionality.

changedetectionio/blueprint/imports/templates · high confidence

New Jinja2 template extensions for time formatting and regex replacement

Templates now support the \{% now %}\ tag for timezone-aware date and time rendering (powered by the Arrow library) and the \\|regex\_replace\ filter for pattern-based string replacements. These capabilities are provided by new custom Jinja2 extensions and filters within the \jinja2\_custom\ module, which also includes security safeguards such as sandboxing, input size limits, and ReDoS protection for regex operations.

_changedetectionio/jinja2\custom · high confidence

New Levenshtein similarity and word count condition plugins

The application now includes two new condition plugins that allow users to base change detection rules on text similarity and content length. The Levenshtein plugin calculates the edit distance and similarity ratio between the latest and previous snapshots, displaying these metrics in the edit page UI (skipping calculation for snapshots exceeding 100,000 characters to prevent performance issues). The word count plugin provides a simple count of words in the latest snapshot, also exposed in the UI stats. Both plugins register new field choices for conditions and integrate with the existing plugin system.

changedetectionio/conditions/plugins · high confidence

New Ternary Boolean UI widget for settings

A new \TernaryNoneBooleanField\ widget is introduced in the \widgets\ module, providing a horizontal radio-button interface that supports three states (Yes/No/Default) or a strict two-state (Yes/No) mode. This component allows users to configure settings with custom labels and HTML content (such as icons or styling) for each option, while correctly handling True, False, and None data values in forms.

changedetectionio/widgets · high confidence

New backup management interface with restore capability

The application now provides a dedicated UI for managing backups, featuring a new 'Create' tab to request and download backup archives and a 'Restore' tab to upload and restore from .zip files. The restore interface allows users to selectively include or replace existing watches and groups, with explicit limits on upload and decompressed file sizes. This change also introduces CSRF protection for backup-related actions to enhance security.

changedetectionio/blueprint/backups/templates · high confidence

New condition-based filtering system with plugin support

Users can now define complex conditions to filter or trigger actions based on page content, such as checking if text starts or ends with specific strings, matching regular expressions, or comparing extracted numeric values (like prices) against thresholds. This feature introduces a plugin architecture that allows extending available operators and data fields, and provides a UI for configuring these rules with immediate verification against the current page snapshot.

changedetectionio/conditions · high confidence

New diff rendering module with word-level highlighting and change extraction tokens

A new \changedetectionio/diff\ module has been introduced to handle diff rendering, providing word-level inline highlighting for changes using the \diff-match-patch\ library. This module supports multiple tokenization strategies (simple whitespace and HTML-aware) to ensure accurate diffing of text and HTML content. It introduces new notification tokens \{{diff\_changed\_from}}\ and \{{diff\_changed\_to}}\, which allow users to extract only the specific removed or added fragments from a diff, rather than the entire line. The implementation includes logic to handle whole-line replacements and inline changes, with configurable options to include or exclude change type prefixes in the output.

changedetectionio/diff · high confidence

New fast OpenCV-based screenshot comparison processor

A new image comparison processor has been added that uses OpenCV for visual change detection, offering 50-100x faster performance than the previous SSIM implementation. This processor supports configurable sensitivity thresholds, region-based comparison via visual selectors or bounding boxes, and generates three-panel diff views with red-highlighted changes. It includes MD5 pre-checks to skip identical images, automatic downscaling for large screenshots, and optional Pixelmatch support for better anti-aliasing detection in text-heavy screenshots.

_changedetectionio/processors/image\_ssim\diff · high confidence

New import functionality for URLs, Distill.io, and XLSX files

Users can now import existing watch lists directly into the application via a new import interface. This feature supports bulk importing from plain text URL lists, migrating monitors from Distill.io via JSON export, and importing from XLSX files (including Wachete format and custom column mappings). The import process respects the configured watch limit and handles errors by reporting skipped items, allowing users to retry failed entries.

changedetectionio/blueprint/imports · high confidence

New interactive UI components for Browser Steps, Conditions, and Diff viewing

The application introduces several new JavaScript modules to enhance the user interface. A new 'Browser Steps' interface allows users to visually select elements on a webpage for automated actions, featuring a session keep-alive timer and improved error reporting with screenshots. A 'Conditions' module enables users to define and verify complex rules (e.g., value comparisons) with live feedback against the current snapshot. Additionally, a new 'Comparison Slider' provides an interactive before/after image view for diffs, while 'Diff Overview' and 'Diff Render' scripts improve navigation between change versions and provide a visual minimap for jumping to specific differences. A new 'CSRF' script ensures all AJAX requests include CSRF tokens for security.

changedetectionio/static/js · high confidence

New price and stock history view for restock monitors

Users monitoring out-of-stock items now have a dedicated interface to view price and stock history. This new template introduces a tabbed view that displays a graph of price changes over time alongside a detailed data table, with an option to export the history as an XLSX file. It also includes a tab for viewing the most recent screenshot of the product page, helping users track both pricing trends and stock availability status visually.

_changedetectionio/processors/restock\diff/templates · high confidence

New restock and price tracking processor with configurable alerts and history visualization

A new \restock\_diff\ processor is introduced to monitor product availability and price changes. It allows users to configure specific triggers for stock status transitions (in-stock only, all changes, or off) and price movements (absolute min/max thresholds or percentage changes since the last check). The processor exposes new notification tokens (\restock.price\, \restock.previous\_price\, etc.) and provides a dedicated history view that renders price timelines as line graphs with statistical summaries (min, max, median, quartiles) and an option to export the full history as an Excel file.

_changedetectionio/processors/restock\diff · high confidence

New tag and group management interface with custom styling and bulk actions

The application now provides dedicated templates for managing organizational tags and groups. Users can create and edit tags with custom background colors, view the number of watches associated with each group, and perform bulk actions such as muting notifications, rechecking all watches in a group, unlinking watches, or deleting the group entirely. The edit interface includes tabs for general settings, AI/LLM configuration, filters & triggers, and notifications, allowing granular control over how tags apply to watches.

changedetectionio/blueprint/tags/templates · high confidence

New tag/group management interface with AI and restock configuration

This change introduces a new dedicated blueprint for managing tags (also referred to as groups), allowing users to create, edit, and delete tags from a central overview page. The new interface supports configuring custom background colors for tags (with strict validation to prevent CSS injection), setting URL matching patterns to auto-apply tags to watches, and configuring AI-driven change detection and summary prompts specifically for the group. It also integrates restock and price monitoring settings into the tag configuration, enabling users to set up tags that apply to all watches with specific price or restock limits.

changedetectionio/blueprint/tags · high confidence

New text/JSON diff processor with advanced filtering and live preview

The \text\_json\_diff\ processor has been introduced to handle text, HTML, JSON, and PDF content changes. It supports a comprehensive set of text filters including extract, ignore, trigger, and subtractive selectors, along with new capabilities like trimming whitespace, removing duplicate lines, and extracting lines containing specific text. The processor features a live preview mechanism that allows users to see the output of filters in real-time, including line number mapping for ignored text even after extraction transformations. It also integrates with LLM capabilities for intent-based evaluation and diff summaries, and includes improved UTF-8 handling and error management for malformed JSON responses.

_changedetectionio/processors/text\_json\diff · high confidence

New visual diff and image comparison UI styles

The application introduces dedicated CSS files for the difference page and image comparison views, providing a modernized layout for side-by-side screenshot comparisons with a draggable slider, a visual diff jump indicator, and improved readability for text diffs. Additionally, the static styles directory now includes the \flag-icons\ library to support country flag displays in the interface.

changedetectionio/static/styles · high confidence

Processor plugin architecture and API schema extension

The processor system has been refactored to support a pluggable architecture, allowing new domain-specific processors (such as the new 'restock\_diff' for stock monitoring) to be registered via the plugin manager or as built-in sub-packages. Processors can now extend the Watch API schema by providing an \api.yaml\ file, which automatically merges custom configuration fields into the API specification. This change introduces a standardized interface for processor discovery, metadata retrieval, and submodule loading (e.g., for custom difference views or data extraction), enabling users to monitor non-HTML content types like DNS changes or restock events through extensible, schema-driven processor modules.

changedetectionio/processors · high confidence

Proxy health check tool for watches

A new endpoint has been added to allow users to test the connectivity and response of configured proxies against a specific watch. This feature enables users to verify if a proxy is working correctly by triggering a scan that reports the status (OK, Error, or Running) and any specific issues encountered, such as 404s, access denials, or filter mismatches.

_changedetectionio/blueprint/check\proxies · high confidence

RSS feed support with configurable content formats and timezone fixes

This change introduces RSS feed generation for the application, providing routes for a main feed, individual watch feeds, and tag-filtered feeds. Users can now consume change notifications via standard RSS readers. The implementation allows configuring the RSS content format to match the notification body or use a system default, with options for HTML or plaintext output. A key behavioral fix ensures that RSS pubDate timestamps are correctly handled in non-UTC containers by explicitly using UTC time, preventing incorrect date shifts. Additionally, the code includes validation for RSS access tokens and sanitization of invalid characters in feed content to ensure XML validity.

changedetectionio/blueprint/rss · high confidence

Removals

Removal of legacy backend components

The legacy backend implementation files (backend.py, nocache.py, and store.py) have been removed from the codebase. This eliminates the previous Flask-based server entry point, the custom HTTP cache-control decorator, and the JSON-file-based data store class, indicating a structural shift in how the application's core logic and data persistence are handled.

backend · high confidence

Removal of obsolete dev-docker container setup

The legacy development Docker environment located in backend/dev-docker has been removed. This change deletes the Dockerfile, build script, and the sleep.py utility that previously ran a Python 3.8 container, eliminating this specific local development tooling from the project.

backend/dev-docker · high confidence

Security

Introduces Pydantic-based validation for LLM settings and refactors core model structures

The application now uses Pydantic models to validate and enforce the schema for LLM configuration, preventing mass-assignment vulnerabilities by rejecting unknown fields. This change also introduces new model files for App settings, Tags, and Watch entities, establishing a foundation for future Pydantic migration of the entire data layer. Users will see improved security around LLM configuration inputs and a more structured approach to managing watch and tag settings, though the core watch and app settings remain dict-based for now.

changedetectionio/model · high confidence

Security fix for reflected XSS and new sidebar display modes

This update addresses a reflected Cross-Site Scripting (XSS) vulnerability ([GHSA redacted]) in the /diff/\<uuid\>/download-patch endpoint by introducing a helper function that forces error responses to use the 'text/plain' content type, preventing the browser from parsing user-supplied input as HTML. Additionally, the application now supports configurable left-rail sidebar display modes, allowing users to choose between an expandable rail, a permanently expanded view, or a minimal constant-size view.

changedetectionio/blueprint · high confidence

Architecture

Datastore refactored to use individual watch files and atomic writes

The internal data storage mechanism has been restructured to save each watch as an individual JSON file rather than writing a single large JSON database file on every change. This change introduces atomic file writes (using temporary files and rename operations) to improve data integrity and crash safety, and adds support for optional \orjson\ serialization for faster performance. Users benefit from improved reliability during upgrades and reduced risk of data corruption, as the system now backs up the datastore before schema migrations and handles file I/O more robustly.

changedetectionio/store · high confidence

UI restructured into modular Flask blueprints

The UI application logic has been refactored from a monolithic structure into distinct, modular Flask blueprints (edit, notification, preview, queue, views, and diff). This change organizes the interface code into separate files, improving maintainability and allowing specific UI components like the queue inspector and processor-aware diff/preview pages to be managed independently.

changedetectionio/blueprint/ui · high confidence

Behavioural changes

Background backup creation and restore with security hardening

The backups module now supports creating and restoring backups in the background via a new UI, preventing UI blocking during large operations. This update introduces strict security controls for the restore process, including zip-slip path traversal prevention, zip-bomb decompression size limits, and UUID validation for imported watch and tag directories. Additionally, backup downloads are now restricted to verified backup filenames, and incomplete or running backups are hidden from the download list to ensure data integrity.

changedetectionio/blueprint/backups · high confidence

Browser Steps UI now uses a dedicated asynchronous event loop

The Browser Steps feature has been refactored to run its browser automation tasks in a dedicated, thread-safe asynchronous event loop. This architectural change ensures that interactive browser interactions (such as clicking, typing, and scrolling) do not block the main Flask application thread, leading to a more responsive UI and preventing race conditions or timeouts associated with the previous synchronous connection model.

_changedetectionio/blueprint/browser\steps · high confidence

Complete UI overhaul with new sidebar, dark mode, and modern components

The interface has been completely restyled with a new left-rail navigation sidebar that supports minimal (icon-only) and always-expanded modes, a comprehensive dark mode theme, and a modernized login form. The watch list now features a three-pane 'Add Watch' workspace with a live visual selector, while the Browser Steps interface uses a responsive flexbox layout. Additional updates include a mobile hamburger menu, AI/LLM summary rows in the watch list, a sticky live filter preview, and new styling for conditions tables, pagination, and notification bubbles.

changedetectionio/static/styles/scss/parts · high confidence

Expanded text filtering and AI change summary controls in the watch edit interface

The watch and group edit pages now include dedicated UI sections for advanced text processing and AI-driven change summaries. Users can configure new text filters such as 'Extract lines containing text', 'Extract text', 'Text to ignore', 'Trigger text', and 'Text that should not be present', along with a 'Strip ignored lines' toggle to refine how page content is compared. Additionally, a new AI section allows users to set change intents and custom change summary prompts, with support for inheriting these prompts from parent groups and appending to them at the watch level.

changedetectionio/templates/edit · high confidence

German translation file updated

The German language file (messages.po) has been updated with new translations for the 'Add watch' interface, including browser selection prompts and backup/restore workflow labels.

changedetectionio/translations/de · high confidence

Improved Discord notification styling and custom HTTP handler format support

Discord notifications now use colored embeds to visually distinguish added (green), removed (red), and changed (orange/blue) content, replacing the previous broken HTML formatting. Additionally, custom HTTP notification handlers (POST, PUT, etc.) now correctly preserve the \format=\ URL parameter, ensuring that HTML or Markdown bodies are sent intact without being stripped to plain text.

_changedetectionio/notification/apprise\plugin · high confidence

LLM settings refactored with SSRF and credential-exfiltration guards

The LLM configuration interface has been restructured to use Pydantic models for validation and to enforce stricter security checks. The system now validates the LLM \api\_base\ URL against SSRF attacks and prevents credential exfiltration by refusing to use stored API keys when the request targets a different endpoint than the one saved in the configuration. Additionally, the UI now supports disabling all LLM features via the \LLM\_FEATURES\_DISABLED\ environment variable and provides specific handling for self-hosted OpenAI-compatible endpoints.

changedetectionio/blueprint/settings · high confidence

Major UI overhaul with new navigation, settings tabs, and notification token documentation

The application interface has been completely redesigned to improve usability and consistency. A new left-rail navigation sidebar and mobile drawer provide clearer access to Page Watches, Watch Groups, and the Queue, while the top menu now features global Mute and Pause buttons for all watches. Settings pages have been reorganized into vertical sub-tabs for better structure. The notification configuration UI now includes a comprehensive, expandable reference table for all available Jinja2 tokens (such as \{{diff}}\, \{{watch\_title}}\, and \{{llm\_summary}}\), and a dedicated \IMPORTANT.md\ file has been added to clarify template file extension requirements for autoescaping.

changedetectionio/templates · high confidence

Major UI overhaul with new watch editing, diff, and queue management pages

The user interface has been significantly refactored, introducing new templates for core workflows. The watch editing interface now features a tabbed layout with dedicated sections for General, Request, Browser Steps, Visual Filter Selector, AI/LLM, Filters & Triggers, and Notifications, including support for optional override links and history length limits. A redesigned diff page allows users to compare snapshot versions with granular filters (words, lines, whitespace, added/removed/replaced) and displays AI-generated change summaries when configured. A new queue management page provides a live view of worker status and pending checks, allowing users to clear the queue. Additionally, a new 'Clear All History' page enables users to remove version history for all watches while preserving the URL list, and the preview page has been updated to support keyboard navigation and highlight triggered/ignored lines.

changedetectionio/blueprint/ui/templates · high confidence

Modernized stylesheet architecture and new image diff visualization

The application's styling has been refactored into a modular SCSS system, introducing a new \\_settings.scss\ file for shared variables and breaking the main stylesheet into specific partials (e.g., \diff.scss\, \diff-image.scss\). This update adds a dedicated interactive image comparison slider for visual diffs, featuring a draggable handle, checkered transparency backgrounds, and side-by-side screenshot panels. Additionally, the diff page layout has been improved with sticky headers that maintain background continuity during scroll, and the overall app shell now uses a flex-based layout for better responsiveness.

changedetectionio/static/styles/scss · high confidence

New browser-injected resources for favicon fetching, element locking, and stock detection

Added a new \res/\ directory containing JavaScript resources injected into the browser context to improve scraping reliability and performance. \favicon-fetcher.js\ now fetches multiple favicon candidates in parallel under a shared 3-second deadline to prevent hangs and prefers the highest-resolution icon. \lock-elements-sizing.js\ and \unlock-elements-sizing.js\ temporarily lock the dimensions of elements in the first viewport during full-page screenshot capture to prevent CSS media queries from resizing headers or ads, ensuring consistent visual diffs. \stock-not-in-stock.js\ provides an expanded, multilingual list of out-of-stock phrases for restock detection, and \xpath\_element\_scraper.js\ includes fixes for handling invisible elements and improving selector generation.

_changedetectionio/content\fetchers/res · high confidence

New exception classes for browser and fetcher errors

A new module \changedetectionio.content\_fetchers.exceptions\ has been introduced, defining specific exception classes for various content fetching failures. These include \Non200ErrorCodeReceived\, \JSActionExceptions\, \BrowserConnectError\, \BrowserFetchTimedOut\, \BrowserStepsStepException\, \PageUnloadable\, \EmptyReply\, \ScreenshotUnavailable\, and \ReplyWithContentButNoText\. This change allows the application to handle and distinguish between different types of browser and HTTP errors more precisely, such as connection timeouts, JS action failures, and empty replies, improving error reporting and handling in the content fetching subsystem.

_changedetectionio/content\fetchers/exceptions · high confidence

New translation guidelines and updated language catalogs

The translations directory now includes a comprehensive guide for contributors and translators, enforcing rules to prevent translation breakage by requiring entire sentences as translatable strings (avoiding fragmented msgids) and providing specific policies for handling HTML markup and CJK languages. Additionally, new translation catalogs have been added for Ukrainian and Indonesian, while existing catalogs for Russian and others have been updated to reflect the latest UI strings.

changedetectionio/translations · high confidence

Real-time UI updates via WebSocket

The application now uses Socket.IO to push live updates to the browser, replacing the previous polling mechanism. This enables immediate reflection of watch status changes (checking, completed, errors), queue length, and favicon updates without page reloads. Users can also perform operations like pause, mute, and recheck in real-time, with changes instantly broadcast to all connected clients.

changedetectionio/realtime · high confidence

Refactored content fetcher architecture with improved memory management and security

The content fetching system has been restructured to improve stability, security, and performance. A new modular architecture separates fetcher logic into distinct modules (Playwright, Puppeteer, Requests) with a centralized capability resolution system. Memory usage is significantly reduced for large screenshots by offloading image stitching to a separate subprocess, preventing memory leaks in the main process. Security is enhanced by enforcing URL validation on all navigation actions, including Browser Steps, to prevent Server-Side Request Forgery (SSRF) attacks via file:// or private IP addresses. Additionally, screenshot capture now supports configurable maximum heights and viewport element locking to prevent layout shifts during capture.

_changedetectionio/content\fetchers · high confidence

Refactored notification formatting and service-specific styling

The notification system has been refactored to improve how change diffs are rendered across different channels. HTML notifications now use a dedicated 'HTML Color' format that applies specific CSS styles to highlight added, removed, and changed text, while email notifications are wrapped in a monospace-safe HTML template to preserve layout in clients like Gmail. Service-specific handling has been added for Discord and Telegram, replacing broken HTML tags with native markdown (such as strikethrough and bold) to ensure diffs display correctly. Additionally, the 'Markdown' format has been renamed to 'Markdown to HTML' to clarify that it is converted for apprise before delivery.

changedetectionio/notification · high confidence

Removal of custom static CSS styles

The custom CSS file (backend/static/css/styles.css) has been deleted, removing specific styling rules for the body text color, link colors, and the content section layout. Users will no longer see these custom visual adjustments, and the interface will rely on inherited base styles or other remaining style sources.

backend/static · high confidence

Removal of legacy Pure CSS layout and watch overview template

The \base.html\ layout template and \watch-overview.html\ page template have been deleted from the backend. This removes the previous implementation that relied on the Pure CSS framework for the navigation menu and the watch management interface, indicating a shift away from this specific UI structure in favor of a new design or templating approach.

backend/templates · high confidence

Restructured settings UI with dedicated notification and AI/LLM configuration tabs

The Settings interface has been reorganized into distinct tabs, introducing a new 'Notifications' section for configuring Apprise-based alerts and a new 'AI / LLM' tab for managing AI provider connections, model selection, and intent-based filtering. The main settings page now includes tabs for General, Fetching, Filters, UI Options, RSS, Backups, Time & Date, Proxies, and Info, while the previous global notification form has been moved to its own dedicated route. The AI tab provides a master switch to enable or disable all LLM features, supports multiple providers (including OpenAI-compatible endpoints), and includes a security disclaimer for third-party data transfer.

changedetectionio/blueprint/settings/templates · high confidence

Updated Korean language translations

The Korean (ko) translation file has been updated with new translations for various UI strings, including watch creation, backup/restore, and system settings, ensuring the interface is correctly localized for Korean-speaking users.

changedetectionio/translations/ko · high confidence

Updated Simplified Chinese translations for the web interface

The Simplified Chinese (zh) translation file has been updated with new and corrected UI strings, covering areas such as adding watches, backup management, and browser configuration. This ensures that users selecting Simplified Chinese see consistent and accurate labels throughout the application.

changedetectionio/translations/zh · high confidence

Watch list rows extracted for real-time updates and improved performance

The watch list template has been refactored to extract the individual watch row into a separate template file (watch-overview-single-row.html). This allows the same markup to be re-rendered on the server and pushed via Socket.IO for real-time row resynchronization, ensuring the UI never drifts from the server state. The change also introduces lazy loading for favicons using an Intersection Observer to prevent blocking realtime operations, and adds support for LLM-generated change summaries and price history graphs in the watch overview.

changedetectionio/blueprint/watchlist/templates · high confidence

Watchlist filtering and row rendering refactored for consistency and real-time updates

The watchlist interface now uses a shared, centralized filtering logic (in \filters.py\) that serves as the single source of truth for both the main watch table and bulk actions, ensuring that operations like 'mark all viewed' or 'recheck' always apply to the exact same set of watches currently displayed. Additionally, the context required to render individual watch rows has been extracted into \row\_context.py\ to guarantee that rows updated in real-time via WebSocket match the server-rendered table exactly, preventing visual drift. This change also introduces an endpoint to fetch all matching watch UUIDs, enabling client-side selection across paginated results.

changedetectionio/blueprint/watchlist · high confidence

Test coverage

Added SMTP notification tests with a dedicated test server; Added test coverage for LLM evaluation, prompt building, and feature toggles; Added tests for Apprise notification plugin assets and custom API handlers; Added tests for SOCKS5 proxy configuration and validation; Added tests for Visual Selector and Browser Steps functionality; Added tests for browser fetcher content retrieval, custom JS execution, and interstitial redirect handling; Added tests for custom browser URL configuration; Added tests for plugin system capabilities; Added tests for proxy configuration and selection; Added tests for restock detection and price change tracking; Added unit tests for security, content processing, and configuration logic; Expanded test coverage for access control, filters, and UI workflows.

Dependencies

Major dependency overhaul and build system modernization

The project has replaced its legacy, fragmented Python dependency files (backend/requirements.txt and backend/dev-docker/requirements.txt) with a single, consolidated requirements.txt that upgrades core frameworks to Flask 3.1, WTForms 3.2, and Apprise 1.13.1, while introducing new capabilities like LLM integration via LiteLLM, JSON logic conditions, and modern CSS tooling. This change also introduces dedicated package.json files for the static styles (using Sass) and API documentation (using Redocly), establishing a modern Node.js-based build pipeline for the UI and docs alongside the updated Python runtime.

(dependencies) · high confidence

Housekeeping

French language translations updated; Updated Czech, Italian, and Ukrainian translation catalogs.

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Baseline

  • First survey — no prior run to compare against. CAI 45.

Lenses

  • Code Health 52
  • Architecture 98
  • Maturity 71
  • Readiness 37
  • Security 68
  • Accessibility 41

Changes since last survey

  • 300 commits — 239 feature/other, 61 fixes

By area

  • changedetectionio/translations — 77 commits
  • changedetectionio/blueprint — 29 commits
  • changedetectionio/static — 27 commits
  • (root) — 24 commits
  • changedetectionio/init.py — 20 commits
  • changedetectionio/tests — 17 commits
  • changedetectionio/content_fetchers — 16 commits
  • changedetectionio/processors — 12 commits
  • .github/workflows — 10 commits
  • changedetectionio/llm — 10 commits
  • changedetectionio/api — 8 commits
  • changedetectionio/flask_app.py — 7 commits
  • changedetectionio/html_tools.py — 6 commits
  • (repo) — 5 commits
  • changedetectionio/forms.py — 5 commits
  • changedetectionio/notification — 5 commits
  • changedetectionio/notification_service.py — 4 commits
  • changedetectionio/store — 3 commits
  • changedetectionio/templates — 3 commits
  • changedetectionio/diff — 2 commits

Notable commits

  • fix: API - Invert changes_only flag for include_equal parameter, add test, fixes changesOnly option for history diff API call (#3976)
  • fix: CSRF - Test fix (#4316)
  • fix: Fix - diff_changed_to causing some missed notifications #4063 #3818 (#4066)
  • fix: Fix Spanish translations for 'Changed' and 'Last Changed' (#4160)
  • fix: Fix SCREENSHOT_MAX_HEIGHT not enforced: cap viewport step_size and clip stitched output to max capture height #3810 (#4030)
  • fix: Fix strings not rendered in user's locale despite having .po entries (#4051)
  • fix: Fix untranslated labels on mobile watchlist view (#4064)
  • fix: Fix/pr 4110 czech l12n catalog sync (#4145)
  • fix: Fix/step failure notification crash (#4041)
  • fix: HTML hygiene fix/improvement (Dont allow unescaped HTML to become real HTML in notifications)
  • fix: Improved content type detection - adding regression test
  • fix: LIBXML Data integrity fix, libxml must be locked across threads for any XML parsing (#4325)
  • fix: LLM - Counter stats - Fix LLM token counter race condition (#4276)
  • fix: Notifications - Fix 'str' object is not callable when {{ diff(...) }} callable tokens are used with HTML/htmlcolor output (#4161)
  • fix: Restock - test fix
  • fix: Restock detection - fix inverted condition that skipped the OpenGraph availability fallback (#4262)
  • fix: Scheduler+API Bug - if an invalid timezone was set (through edit of watch or API) it could have crashed the scheduler, Added timezone to the official API docs (#4350)
  • fix: Security: XPath json-doc() Arbitrary File Read Bypass ( Similar fix as [CVE redacted] )
  • fix: Tests - Fix TestHistoryPathTraversal on macOS, and cover the containment check (#4390)
  • fix: UI - CSS - Header menu item color fix
  • …and 280 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

dgtlmoon/changedetection.io was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 18 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 0426ce04248c1d4f10ac921b1f9b045c863536b6 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-5d04157a340d.