Page content monitoring (Content monitor)
Content monitor watches the content, not the resource availability: Notifly fetches the specified URL every N seconds, extracts the value of interest from the response and compares it with the previous one. As soon as the value changes — an alert is sent. This is an active monitor (Notifly initiates the check), but it answers the question “what changed on the page” rather than “is the site up”.
Typical use cases:
- Price — track the price of a product on a store page or a competitor’s site.
- Status / availability — “in stock” ↔ “out of stock”, order status, service status.
- Competitor content — a new blog post appeared, the price list changed, the changelog updated.
- JSON API — the value of a field in a public JSON response (rate, balance, version).
Extraction modes
Section titled “Extraction modes”What to compare is defined by the mode (mode). Five modes are supported:
mode | What is extracted | Field selector |
|---|---|---|
hash | SHA-256 of the entire response body — alert on any page change | not needed |
json | Value by JSONPath from a JSON response | required — JSONPath, e.g. $.price or $.items.0.status |
text | Substring by regular expression from the response text | regex; if empty — behaves like hash |
css | Text of the first element matched by a CSS selector | required — valid CSS selector |
xpath | Text of the first node matched by an XPath expression | required — valid XPath expression |
The check logic is the same for all modes: extract the value → compare with the stored
lastValue → if different, send an alert and remember the new value. The first check
just stores the current value and does not send an alert.
Multiple rules in one monitor
Section titled “Multiple rules in one monitor”Instead of a single mode+selector you can provide an array of rules (rules) —
up to 20 rules per monitor. Each rule is { "mode", "selector", "label" },
where label is an optional human-readable name. An alert is triggered if any
rule changed. This is convenient when you need to monitor several values on the same page
(e.g., price + availability + rating).
"rules": [ { "mode": "css", "selector": ".product-price", "label": "Цена" }, { "mode": "css", "selector": ".availability", "label": "Наличие" }, { "mode": "text", "selector": "Скидка\\s+\\d+%", "label": "Скидка" }]If rules is set, top-level fields mode/selector are ignored. If rules
is empty — the single mode (mode+selector) works, preserved for backward
compatibility.
JavaScript pages: useBrowser
Section titled “JavaScript pages: useBrowser”By default the page is loaded via a plain HTTP GET. If the needed value
is injected by scripts in the browser (SPA, lazy-loaded price, etc.),
enable the flag useBrowser: true — then the page is rendered via headless
Chromium and values are extracted from the final DOM after JS execution.
Selector testing and selection
Section titled “Selector testing and selection”Before creating a monitor, it is convenient to try and validate a rule on the fly — there are two endpoints that do not require creating a monitor.
Test a rule — POST /content-monitor/test-rule
Section titled “Test a rule — POST /content-monitor/test-rule”Loads the page and applies a single rule, returning the extracted value or a clear error:
curl -X POST "$NOTIFLY_URL/content-monitor/test-rule" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <client-token>" \ -d '{ "url": "https://example.com/product/42", "useBrowser": false, "mode": "css", "selector": ".product-price" }'# → {"ok":true,"value":"1 299 ₽"}Response: ok (boolean), value (extracted value, truncated to 200 characters),
error (error text, if the rule failed) and note (diagnostics, e.g. about browser mode fallback to GET).
Suggest a selector using AI — POST /content-monitor/suggest-selector
Section titled “Suggest a selector using AI — POST /content-monitor/suggest-selector”Notifly loads the page once, compresses the HTML and in one request to the LLM
chooses the mode and selector according to your description. The result is always
verified on the real page content, so the response contains a valid sampleValue:
curl -X POST "$NOTIFLY_URL/content-monitor/suggest-selector" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <client-token>" \ -d '{ "url": "https://example.com/product/42", "useBrowser": false, "prompt": "следить за ценой товара" }'The response includes: mode, selector, label, sampleValue (current value on the page),
reason (why), confidence (high/medium/low), alternatives (other candidates) and fallback (true if the LLM is unavailable and the selector was chosen heuristically).
The prompt field is up to 500 characters. A request like “monitor the whole page”
will immediately return hash mode without calling the LLM.
Creating a monitor
Section titled “Creating a monitor”Via the dashboard
Section titled “Via the dashboard”- Open app.notifly.ru → Monitors → Content.
- Enter the URL, choose a mode (or click “Suggest selector” and describe in words
what to monitor), enable
useBrowserif needed. - Use the “Test” button to ensure the extracted value is exactly what you need.
- Set the interval, alert text and priority — and save.
Via the REST API — POST /content-monitor
Section titled “Via the REST API — POST /content-monitor”Single mode (monitoring one CSS value):
curl -X POST "$NOTIFLY_URL/content-monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <client-token>" \ -d '{ "appid": 12345, "name": "Цена товара #42", "url": "https://example.com/product/42", "mode": "css", "selector": ".product-price", "useBrowser": false, "intervalSec": 3600, "timeoutSec": 15, "alertMessage": "Цена товара #42 изменилась!", "alertPriority": 7 }'Multiple mode (several rules on one page):
curl -X POST "$NOTIFLY_URL/content-monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <client-token>" \ -d '{ "appid": 12345, "name": "Карточка товара", "url": "https://example.com/product/42", "rules": [ { "mode": "css", "selector": ".product-price", "label": "Цена" }, { "mode": "css", "selector": ".availability", "label": "Наличие" } ], "intervalSec": 3600, "alertMessage": "Изменилось содержимое карточки товара.", "alertPriority": 5 }'Monitoring a field in a JSON API:
curl -X POST "$NOTIFLY_URL/content-monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <client-token>" \ -d '{ "appid": 12345, "name": "Курс из API", "url": "https://api.example.com/rates", "mode": "json", "selector": "$.usd.value", "intervalSec": 600, "alertMessage": "Курс USD изменился." }'Request fields
Section titled “Request fields”| Field | Type | Required | Description / constraints |
|---|---|---|---|
appid | uint | yes | ID of the application (channel) to send the alert to |
name | string | yes | Monitor name, 1–200 characters |
url | string | yes | Valid http(s) URL |
mode | string | yes* | Single mode: hash / json / text / css / xpath |
selector | string | depends | JSONPath for json, regex for text, CSS for css, XPath for xpath; required for json/css/xpath |
rules | array | yes* | Array of rules {mode, selector, label}, up to 20; alternative to mode+selector |
useBrowser | bool | no | true — render via headless Chromium |
intervalSec | uint | yes | Check interval, 60–86400 seconds |
timeoutSec | uint | no | Load timeout, default 15, maximum 60 |
alertMessage | string | yes | Alert text, 1–2000 characters |
alertTitle | string | no | Alert title |
alertMessageMarkdown | bool | no | Treat alert text as Markdown |
alertPriority | int | no | Alert priority, 0–10 |
* You must set either rules (multiple mode) or mode+selector (single mode).
If rules is non-empty — mode/selector are ignored.
Lifecycle and statuses
Section titled “Lifecycle and statuses”A new monitor is created with status pending and is checked almost immediately
(nextCheckAt = “now”). After changing “significant” fields (URL, mode, selector,
rules, useBrowser, interval, timeout) the check is rescheduled for “now”.
Cosmetic edits (name, alert title/message, priority) do not shift the schedule.
POST /content-monitor/:id/pause— pause (checks are not performed;nextCheckAtis moved far into the future).POST /content-monitor/:id/resume— resume (status becomespendingagain, check is scheduled for “now”).
The monitor record stores lastValue (last extracted value),
lastError (last load/extraction error), lastCheckAt, nextCheckAt
and alertedAt.
Limits
Section titled “Limits”- Check interval: 60–86400 seconds (1 minute to 24 hours).
- Load timeout: default 15 s, maximum 60 s.
- Up to 20 rules per monitor.
- Alert priority: 0–10;
namelength — 1–200,alertMessage— 1–2000 characters. - Requests originate from the cloud, so the target URL must be accessible from the public internet.
- Browser mode (
useBrowser) works only if the corresponding container is configured on the server.
REST API
Section titled “REST API”All endpoints require a client token (or an MCP code with write rights for mutating operations); the list is available in read-only mode too. More about tokens in First login.
| Method | Path | Description |
|---|---|---|
GET | /content-monitor | List of the user’s content monitors |
POST | /content-monitor | Create a monitor |
POST | /content-monitor/suggest-selector | Suggest mode + selector with AI by description |
POST | /content-monitor/test-rule | Apply one rule to a page (dry-run), return value or error |
PUT | /content-monitor/:id | Update settings (cannot change appid) |
DELETE | /content-monitor/:id | Delete a monitor |
POST | /content-monitor/:id/pause | Pause checks |
POST | /content-monitor/:id/resume | Resume checks |
See also: Active monitors, HTTP monitors, Workflow monitors, Browser-workflow.