Changedetection.io
Монитор изменений веб-страниц на своем сервере: по расписанию забирает страницу, сравнивает с прошлым снимком и шлет сигнал в Telegram, почту или webhook. Главный сценарий - цены и наличие товара у конкурентов, проверки идут с российского IP. Стенд - Fatmetal Cloud Server, версия 0.60.6 с контейнером Chrome.
Вердикт
- магазину и прайс-аналитику: цены и наличие у конкурентов без лимита на число страниц и проверок
- тендерному и юридическому отделу: страницы закупок, реестров и оферт там, где нет RSS и рассылки
- девопсу: дефейс своих сайтов, changelog зависимостей и advisories - рядом с Uptime Kuma
- команде, которой нужны отдельные логины и роли: пароль один на всю инсталляцию
- кому нужен гарантированный обход антибота Ozon и Wildberries - его не дает ни SaaS, ни self-host
- кому нужен аптайм-мониторинг: это Uptime Kuma, здесь следят за содержимым страницы
Что это и какую задачу решает
changedetection.io отвечает на вопрос «что на странице поменялось»: по расписанию забирает URL, приводит HTML к тексту, сравнивает с прошлым снимком и при разнице шлет уведомление. Это не аптайм-мониторинг, а отслеживание изменений на сайте - в том числе на чужом.
Из коробки - фильтры CSS, XPath, JSONPath и jq, триггеры по тексту, регулярки, diff по строкам и словам, расписание с таймзоной и условные правила. Уведомления идут через Apprise: Telegram, email, Discord, Slack, ntfy, webhook - больше 85 каналов.
Фетчера два. Быстрый HTTP без JavaScript встроен в приложение, а настоящий Chrome живет в отдельном контейнере. Только с Chrome работают Visual Selector (выделить нужный блок мышкой), Browser Steps (логин и клики перед проверкой) и скриншоты в уведомлении.
Проект держит один автор: 34 204 звезды на GitHub, версии 0.60.2-0.60.6 вышли за две недели сентября 2026. Интерфейс переведен на 17 языков, русский есть.
Уведомление о снижении цены: свой бот для отслеживания цен
Режим «цена и наличие» встроен в продукт, Telegram-бот делается за минуту, а проверки идут с российского IP.
Режим «Re-stock & Price detection» включается на карточке наблюдения. Продукт вытаскивает цену и статус наличия из микроразметки товарной страницы и дальше сравнивает не текст, а числа и флаг «в наличии».
Условия задаются там же: «цена ниже 5 000», «упала на 10 %», «товар появился». Пока условие не выполнено, уведомлений нет - список из 200 страниц конкурентов не превращается в шум.
Уведомление - одна строка Apprise вида tgram://токен-бота/chat_id. Бота создают через BotFather, между вашим сервером и вашим телефоном нет ни одного чужого сервиса, а число проверок не ограничено ничем, кроме ресурсов VM.
Про российский IP. Visualping, Distill и облако самого вендора ходят на сайты из-за рубежа: часть российских магазинов отдает им другой контент или режет запрос. Своя VM в РФ снимает это одним фактом - такого аргумента нет ни у одного SaaS.
Маркетплейсы - отдельная история. Ozon и Wildberries держат антибот, который может резать и headless Chrome; на стенде их не проверяли, поэтому не обещаем. Продукт штатно умеет прокси на каждую проверку (Settings, вкладка CAPTCHA & Proxies, или файл proxies.json) - туда подключают Bright Data, Oxylabs или свой список. Обычные интернет-магазины и сайты конкурентов антибота, как правило, не держат.
Чем отличается от платных аналогов
Цены сняты со страниц вендоров 15 сентября 2026. SaaS продают одну и ту же лестницу: страницы, проверки в месяц, минимальный интервал.
| Параметр | changedetection.io на своей VM | Облако вендора | Visualping / Distill.io |
|---|---|---|---|
| Цена | 500 ₽/мес за CPU2-RAM4-DISK50, лимитов нет | $8.99/мес, до 5 000 URL | Visualping $14-350/мес, Distill $15-80/мес |
| Проверок в месяц | сколько потянет VM | один Chrome-раннер на все страницы | от 150 до 50 000 по тарифу |
| Откуда идут проверки | с российского IP | EU / USA / Tor | из-за рубежа |
| Chrome для JS-сайтов | свой контейнер, до 10 вкладок | один раннер включен | в старших тарифах |
| Пользователи и роли | один пароль | один пароль | Visualping Business: 5-11 пользователей |
| ИИ-фильтр «важно / не важно» | свой ключ OpenAI, Gemini, Anthropic или Ollama | в подписке с июня 2026 | у Visualping платно |
| Список того, за чем следите | на вашем сервере | у вендора | у вендора |
Против облака вендора self-host денег не экономит: $8.99 и 500 ₽ - один порядок. Экономия в разы начинается против Visualping и Distill, и растет она с частотой, а не с числом страниц: 50 страниц раз в 15 минут - это ~144 000 проверок в месяц, старший тариф Visualping за $350 дает 50 000.
Тех-стек и архитектура
Python и Flask, один процесс под gunicorn, REST API с OpenAPI-спекой. Базы данных нет: состояние - JSON-файлы и текстовые снимки в каталоге /datastore, это единственный том. После деплоя с двумя demo-наблюдениями каталог занимает 200 КБ.
Второй контейнер - dgtlmoon/sockpuppetbrowser: headless Chrome 153 с протоколом Playwright по WebSocket на порту 3000 внутри docker-сети. Приложение находит его по PLAYWRIGHT_DRIVER_URL; наружу порт не торчит и через reverse proxy не проходит.
Порт приложения в апстрим-compose опубликован только на 127.0.0.1:5000 - снаружи нужен reverse proxy. У нас это Caddy: TLS от Let's Encrypt и одна строка конфига; живые статусы проверок через Socket.IO за ним работают без дополнительных настроек.
Минимальная конфигурация
Апстрим системных требований не публикует. Ниже - что реально заняли два контейнера.
| Официальный минимум RAM | не публикуется |
| Реально в простое, оба контейнера | ~95 МиБ (127 МиБ после первой проверки через Chrome) |
| Образы на диске | 3,4 ГБ (378 + 513 МБ в сжатом виде) |
| Занято на диске после деплоя | 5,5 из 48 ГБ |
| Рекомендуем тариф | CPU2-RAM4-DISK50 - 500 ₽/мес |
Важно: без Chrome приложение уместилось бы и в 2 ГБ. Но каждая JS-проверка - вкладка настоящего браузера, до 10 параллельно, плюс полностраничные скриншоты высотой до 16 000 px. Под такой нагрузкой не мерили; 4 ГБ - запас именно под браузер, а не под приложение.
В маркетплейсе Fatmetal
Не хотите ставить руками?
changedetection.io есть в маркетплейсе Fatmetal - можно не повторять установку из этого разбора вручную. Заказываете сервер, за пару минут получаете рабочий сервис на своем домене, валидный TLS, контейнер Chrome и пароль в файле с доступами.
Рекомендуемая конфигурация:
2 vCPU · 4 ГБ RAM · 50 ГБ NVMe от 450 ₽/мес
Развертывание на Fatmetal
Базовый путь - Fatmetal Cloud Server + Ubuntu 24.04 + Docker Compose по апстрим-рецепту, сверху Caddy.
Создать VM
Тариф CPU2-RAM4-DISK50, Ubuntu 24.04. Docker Engine и compose-plugin ставятся из официального apt-репозитория Docker, это около 40 секунд.
Сгенерировать хеш пароля
Пароль задается до первого старта переменной
SALTED_PASS- тот же формат, что и у поля пароля в UI: base64 от 32 байт соли и PBKDF2-HMAC-SHA256 со 100 000 итераций.python3 - <<'EOF' import base64, hashlib, os, getpass pw = getpass.getpass('Пароль UI: ') salt = os.urandom(32) key = hashlib.pbkdf2_hmac('sha256', pw.encode(), salt, 100000) print('SALTED_PASS=' + base64.b64encode(salt + key).decode()) EOFСтроку из вывода кладем в
.envрядом с compose-файлом.Собрать docker-compose.yml
services: changedetection: image: dgtlmoon/changedetection.io:0.60.6 container_name: changedetection restart: unless-stopped ports: - 127.0.0.1:5000:5000 volumes: - changedetection-data:/datastore environment: - SALTED_PASS=${SALTED_PASS} - BASE_URL=https://ваш-домен - USE_X_SETTINGS=1 - TZ=Europe/Moscow - PLAYWRIGHT_DRIVER_URL=ws://browser-sockpuppet-chrome:3000 depends_on: - browser-sockpuppet-chrome browser-sockpuppet-chrome: image: dgtlmoon/sockpuppetbrowser:latest hostname: browser-sockpuppet-chrome restart: unless-stopped cap_add: - SYS_ADMIN environment: - SCREEN_WIDTH=1920 - SCREEN_HEIGHT=1024 - MAX_CONCURRENT_CHROME_PROCESSES=10 volumes: changedetection-data:Приложение пиним на 0.60.6 (или на ветку
0.60). У браузера тегlatestосознанно: нумерованные теги 0.0.x не обновлялись с августа 2025, а latest - от 14 сентября 2026.Поднять стек
docker compose pull docker compose up -d curl -sI http://127.0.0.1:5000/ | head -1 # HTTP/1.1 302 -> /loginКогда образы в кэше, оба контейнера стартуют за 2,15 с, первый ответ приходит через 2,67 с. Если pull упал по таймауту - повторить, см. «Где может сломаться».
Caddy с TLS
ваш-домен { reverse_proxy 127.0.0.1:5000 }Caddy сам выпустит сертификат Let's Encrypt. Первый запрос сразу после рестарта может упасть с TLS internal error - это гонка с выпуском сертификата, через несколько секунд все отвечает.
Первое наблюдение
Добавить URL, во вкладке Request выбрать фетчер Playwright/Chrome, если сайт на JavaScript, включить «Re-stock & Price detection» для товарной страницы и нажать Recheck. Скриншот и снимок появятся после первой проверки.
ИИ-фильтр шума и ключ модели
Две функции 2026 года. «AI change intent» - правило на человеческом языке: «сообщи, только если цена ниже 5 000 рублей». «AI change summary» - краткий пересказ диффа прямо в уведомлении. Провайдер подключается через LiteLLM: OpenAI, Gemini, Anthropic, Ollama или любой OpenAI-совместимый endpoint.
Ключ вводится в Settings, вкладка AI-LLM, включение - на каждом наблюдении отдельно. Для базовой работы - diff плюс уведомление - ИИ не нужен вовсе, это надстройка для тех, у кого сотни страниц и много ложных срабатываний.
Продукту нужен ключ внешней модели, а из России напрямую до OpenAI и Gemini не достучаться. На VPS Fatmetal это уже решено: обращения к моделям идут через прокси api-proxy.fatmetal.net, он входит в сервер и отдельно не заказывается. Код не меняется - достаточно переменных HTTPS_PROXY, HTTP_PROXY и NO_PROXY в окружении контейнера.
Оговорка именно для этого продукта: те же HTTP_PROXY и HTTPS_PROXY в апстрим-compose описаны как прокси для фетчера страниц. Глобальная переменная уведет через прокси и проверки сайтов, а он рассчитан на API моделей, не на интернет вообще. На стенде ИИ-слой не включали; после включения стоит убедиться, что проверки страниц по-прежнему проходят. Выключается целиком переменной LLM_FEATURES_DISABLED=true.
Что измерили после запуска
Стенд: CPU2-RAM4-DISK50, Ubuntu 24.04, Docker 29.8.0, Compose v5.5.1, Caddy 2.11.4. Без нагрузки, сразу после чистого редеплоя.
| Скачивание образов (891 МБ сжатых) | 51,7 с со второй попытки; первая упала через 42,6 с |
| docker compose up -d | 2,15 с |
| Первый HTTP-ответ после команды | 2,67 с |
| RAM в простое | 66,98 МиБ приложение + 27,96 МиБ Chrome = 94,94 МиБ |
| CPU в простое | 0,42 % приложение, 0,01 % Chrome |
| Отклик локально / через Caddy по HTTPS | 4 мс / 229 мс главная, 87 мс страница входа |
| Каталог /datastore после деплоя | 200 КБ |
| От первого SSH до HTTPS-входа | ~17 минут, из них ~4 - ожидание Docker Hub |
Главное: два контейнера в простое держат меньше 100 МиБ - на полтора порядка меньше тарифной ступени в 4 ГБ. Память понадобится не приложению, а Chrome под параллельными JS-проверками, и именно под него взят запас.
Проверено на changedetection.io 0.60.6, сентябрь 2026. На новых версиях результаты могут отличаться.
Где может сломаться
Грабли, на которые наступили при запуске, и одна ошибка, которая воспроизводится стабильно.
Причина. Транзиентный таймаут Docker Hub на крупном слое образа changedetection.io (около 430 МБ) при скачивании из РФ. Воспроизвелся дважды: при деплое упали три попытки из четырех, при контрольном замере - первая из двух.
Решение. Повторить docker compose pull: скачанные слои остаются в кэше, докачивается только остаток. В скриптах установки закладывать повтор pull как штатный шаг.
Открытый UI. Пароля по умолчанию нет, он ставится в Settings после первого входа - между стартом и первым входом инсталляция публична. SALTED_PASS закрывает это окно; переменную читают auth_decorator.py и flask_app.py, формат совпадает с полем в UI.
JS-сайты без Chrome. Встроенный фетчер не выполняет JavaScript - магазин на SPA отдаст пустую страницу. В апстрим-compose контейнер браузера закомментирован: включите его и выберите Playwright-фетчер на наблюдении.
Скриншот не появляется. Продукт пишет скриншот на диск только при первой проверке или при реальном изменении. Переключили наблюдение с HTTP на Chrome и перепроверили статичную страницу - файла не будет. Создавайте наблюдение сразу с нужным фетчером.
Символ @ в логине SMTP. Строка Apprise mailto://user@domain:pass@host ломается: второй @ парсер считает границей учетки, и письмо уходит в пустой хост. Кодируйте @ в логине как %40.
Мониторинг сайта конкурентов и госзакупок: сторож для страницы без RSS
Тот же механизм закрывает любую страницу, у которой нет RSS и рассылки: карточка закупки на zakupki.gov.ru, реестры ФНС, картотека суда, оферта партнера, вакансии и раздел «о компании» у конкурента.
Рецепт один: выделить Visual Selector нужный блок, чтобы не реагировать на баннеры и счетчики, и добавить «trigger text», если важно конкретное слово - «изменения», «отменена», «в наличии».
Госсайты тоже режут иностранные подсети, так что российский IP здесь работает не хуже, чем на магазинах. Для страниц за формой входа есть Browser Steps: логин, клик, ввод - и только потом снимок.
Девопсу: дефейс своих сайтов и страницы advisories с интервалом в минуты, уведомление - в ntfy рядом с алертами Uptime Kuma. Один следит, что сайт жив, другой - что он не изменился. Любое наблюдение отдает RSS, если нужна лента из страницы без ленты.
Безопасность и обновления
Что закрыть перед продом: пароль через SALTED_PASS до первого старта; порт 5000 только на loopback, наружу - Caddy с TLS; BASE_URL и USE_X_SETTINGS=1, иначе ссылки в уведомлениях ведут на localhost. Ключ REST API включен по умолчанию и лежит в Settings, вкладка API.
Пользователей и ролей нет. Если UI нужен нескольким людям, доступ ограничивают на уровне Caddy (basic auth, список IP) или прячут за VPN. Права cap_add: SYS_ADMIN у браузера апстрим сам называет избыточными; на стенде sockpuppetbrowser открывал страницы и без них.
Обновление - пин на минорную ветку: тег 0.60 получает патчи, latest уедет на новую ветку без предупреждения. Релизы и advisories - на GitHub проекта.
docker compose pull && docker compose up -d
Бэкап - один каталог. В Settings есть вкладка Backups с выгрузкой zip, а из консоли достаточно архива тома:
docker run --rm -v changedetection-data:/datastore:ro -v $PWD:/backup alpine \
tar czf /backup/changedetection-$(date +%F).tgz -C /datastore .
Связь с другими стеками
- Uptime Kuma - отвечает «жив ли сервис»; changedetection.io - «что на странице поменялось». Ставят рядом, а не вместо.
- ntfy - приемник уведомлений: схема ntfy:// есть в Apprise, пуш на телефон без Telegram и без чужого сервиса.
- n8n - webhook-уведомление из changedetection.io запускает сценарий: записать цену в таблицу, поставить задачу, сравнить с прайсом.
- Caddy - reverse proxy с автоматическим TLS перед портом 5000, одна строка конфига.
Когда это НЕ ваш выбор
Нужны отдельные логины и роли
Пароль один на всю инсталляцию, папок и прав нет. Команде из пяти человек с разными зонами ответственности это не подойдет; у Visualping Business есть 5-11 пользователей.
Нужен гарантированный обход антибота маркетплейсов
Ozon и Wildberries могут резать проверки даже через Chrome. Прокси на каждое наблюдение перекладывают риск на вас, но не снимают его; ни один SaaS этого тоже не гарантирует.
Нужен визуальный diff «до / после»
Здесь текстовый diff плюс скриншот текущего состояния. Сравнение двух картинок с подсветкой отличий - это Visualping, и там за него платят.
Вы хотите продавать это клиентам как сервис
Код под Apache 2.0, но в репозитории лежит COMMERCIAL_LICENCE.md: предоставление программы третьим лицам как сервиса вендор требует лицензировать отдельно. На своей VM для своих задач ограничений нет.
Частые вопросы
Можно поставить без Docker?
Есть pip-пакет, но Chrome-фетчер все равно живет в отдельном контейнере; единственный путь по апстриму - Docker Compose.
Хватит ли 2 ГБ RAM?
Без Chrome - да: в простое оба контейнера держат ~95 МиБ. С Chrome и параллельными JS-проверками берите 4 ГБ, под нагрузкой не мерили.
Как задать пароль до первого входа?
Переменной SALTED_PASS, скрипт генерации - в разделе про развертывание. UI закрыт с первой секунды жизни контейнера.
Ozon и Wildberries работают?
Не гарантируем: там антибот, на стенде маркетплейсы не проверяли. Обычные интернет-магазины работают штатно, для площадок с защитой есть прокси на каждое наблюдение.
Как слать уведомления в Telegram?
Создать бота через BotFather, вставить строку tgram://токен/chat_id в Notifications и нажать «Send test notification».
Как обновлять?
docker compose pull && docker compose up -d. Держите пин на ветку 0.60 - релизы выходят каждые несколько дней.
Что бэкапить?
Только том /datastore: настройки, история снимков, скриншоты и ключ API. Базы данных нет.
Какие ограничения лицензии?
Apache 2.0, все функции подписки есть в self-host. Коммерческую лицензию вендор требует только за хостинг программы для третьих лиц как сервиса.
Итог
changedetection.io - монитор изменений страниц с режимом «цена и наличие», Chrome для JS-сайтов и уведомлениями в Telegram без чужих сервисов. Два контейнера в простое держат ~95 МиБ, стек стартует за 2,15 с, а проверки идут с российского IP - аргумент, которого нет ни у Visualping, ни у облака вендора. Пароль через SALTED_PASS, Caddy с TLS, пин на ветку 0.60 - и тариф CPU2-RAM4-DISK50 закрывает сотни страниц без лестницы SaaS.
Рекомендуемая конфигурация для установки:
2 vCPU · 4 ГБ RAM · 50 ГБ NVMe
Не хотите устанавливать вручную?
Запустите changedetection.io на этой конфигурации автоматически - от 450 ₽/мес.
Этот стек у нас запущен на тарифе CPU2-RAM4-DISK50. Нашли баг в гайде - напишите, поправим в течение дня.