Browser-workflow monitors (browser automation)
A regular HTTP monitor and content monitor see only the HTML the server returned in the initial response. For modern SPAs, JavaScript-heavy pages and anything hidden behind authentication, that is not enough: the required text often appears only after logging in, several clicks, and frontend rendering.
The Browser-workflow monitor runs a specified sequence of actions in a real headless Chromium — like a small Selenium script — and verifies that the workflow still completes. If any step fails (an element disappeared, text didn’t match, the page did not load) — an alert is sent. Additionally, the monitor can extract text from the page and notify when it changes.
What a script consists of
Section titled “What a script consists of”A monitor is described by the fields:
startUrl— the initial URL (required, onlyhttp/https). Each run starts from it.steps— JSON array of steps, from 1 to 20 items. Executed strictly sequentially.cookies— optional: captured session for authenticated scenarios (see below). Stored encrypted and never revealed externally.proxy— optional egress proxyscheme://[user:pass@]host:portfor sites that block datacenter IPs. Empty — direct connection.timeoutSec— timeout per step. Default60, maximum120.intervalSec— how often to run the workflow. Minimum 300 (5 minutes), maximum86400(one day).alertMessage(required, up to 2000 characters),alertTitle,alertMessageMarkdown,alertPriority(0…10) — what and with what priority to send on failure.notifyOnChange/notifyOnChangeVars— “notify on change” mode for extracted values (see below).
Step (BrowserStep)
Section titled “Step (BrowserStep)”Each element of the steps array is an object:
| Field | Purpose |
|---|---|
name | human-readable step name (required, included in the alert on failure) |
description | natural-language description of the step — used by the AI to pick action + selector |
action | action to perform (see table below) |
selector | CSS selector of the target |
value | value: URL / text / key; supports interpolation {{variable}} |
extractName | variable name for extractText |
auth | authentication step: run only when the session is invalid |
Actions
Section titled “Actions”Exactly nine actions are supported:
action | What it does | Needs selector | Needs value |
|---|---|---|---|
navigate | navigate to URL (value = URL) | — | yes (URL) |
click | click an element | yes | — |
type | type value into a field | yes | text |
select | select value in a <select> | yes | option value |
press | press key value (e.g. Enter) | — | key |
waitFor | wait for a selector to appear | yes | — |
assertText | assert that the selector’s text contains value | yes | expected text |
extractText | extract selector’s text into variable extractName | yes | — |
scroll | scroll the page: value = top | bottom or pixels (300 down, -300 up) | — | — |
Steps click, type, select, waitFor, assertText, extractText
require a non-empty selector — without it creating/updating a monitor will return
400. For navigate value (URL) is required. For extractText extractName is required.
Example steps array
Section titled “Example steps array”We check that after logging in the dashboard shows a balance and it is not “0”:
[ {"name": "Open dashboard", "action": "waitFor", "selector": "#dashboard"}, {"name": "Expand account", "action": "click", "selector": "button.account-toggle"}, {"name": "Wait for balance", "action": "waitFor", "selector": ".balance-value"}, {"name": "Assert not empty", "action": "assertText", "selector": ".balance-value", "value": "₽"}, {"name": "Remember balance", "action": "extractText", "selector": ".balance-value", "extractName": "balance"}]AI-assisted step selection (build-step)
Section titled “AI-assisted step selection (build-step)”Manually choosing CSS selectors is tedious and brittle. That’s why there’s an endpoint
POST /browser-workflow/build-step: you describe a step in words
(description), and the AI selects action and a stable selector, then
immediately verifies the candidate in a real browser and returns the result.
How it works under the hood:
- The service opens
startUrl, applies providedcookiesand replays already confirmedsteps— getting the page into the current state. - The LLM, based on the description and page markup, proposes an action and up to three ranked selector candidates.
- Candidates are cheaply pre-validated against the HTML (syntax + presence on the page), then all are checked in a single browser run.
- If an action worked —
verified: trueis returned along with an example value (sampleValue) forextractText/assertText. If not — the last proposal withverified: falseand an explanation innote.
Request body:
{ "startUrl": "https://app.example.com/login", "steps": [ /* already confirmed steps */ ], "description": "click the “Log in” button", "cookies": [ /* optional: saved session */ ], "proxy": "", "sessionId": "", "timeoutSec": 60}Response:
{ "action": "click", "selector": "button[type=submit]", "value": "", "extractName": "", "label": "Log in", "reason": "...", "sampleValue": "", "verified": true, "availableVars": ["balance"], "cookies": [ /* resulting session cookies */ ]}The description field — 1 to 500 characters. availableVars shows variables
already extracted by previous steps (via extractText) and available for
interpolation {{var}} in this step. Returned cookies should be accumulated on
the client and passed to the next build-step so you don’t have to repeat
authenticated steps again.
Authenticated scenarios: capturing cookies
Section titled “Authenticated scenarios: capturing cookies”To monitor pages behind login you need a valid session. The endpoint
POST /browser-workflow/login performs login steps (type password, click
button, etc.) in a headless browser and returns the final cookies in plaintext — you then pass them in the cookies field when creating/updating a monitor,
where they are encrypted before storage.
curl -X POST "$NOTIFLY_URL/browser-workflow/login" \ -H "X-Notifly-Key: C..." \ -H "Content-Type: application/json" \ -d '{ "startUrl": "https://app.example.com/login", "steps": [ {"action": "type", "selector": "#email", "value": "me@example.com"}, {"action": "type", "selector": "#password", "value": "secret"}, {"action": "click", "selector": "button[type=submit]"} ], "timeoutSec": 60 }'Response:
{ "cookies": [ /* array of cookies */ ], "count": 7, "url": "https://app.example.com/dashboard" }Test run (test-step)
Section titled “Test run (test-step)”Before saving, the entire workflow can be run via
POST /browser-workflow/test-step — this is the “Check” button. The service executes all
steps and reports whether it reached the end.
curl -X POST "$NOTIFLY_URL/browser-workflow/test-step" \ -H "X-Notifly-Key: C..." \ -H "Content-Type: application/json" \ -d '{ "startUrl": "https://app.example.com/dashboard", "cookies": [ /* saved session */ ], "steps": [ /* full workflow */ ], "timeoutSec": 60 }'Response:
{ "ok": true, "failedStep": -1, "error": "", "url": "https://app.example.com/dashboard", "cookies": [ /* resulting cookies for the whole session */ ], "count": 7, "vars": { "balance": "12 340 ₽" }}If the workflow failed, ok: false, and failedStep will point to the index of the failing step and
error — the reason. On success vars contains all extracted extractText
values — handy to immediately verify that the correct data is being captured.
”Notify on change” mode
Section titled “”Notify on change” mode”If you enable notifyOnChange, the monitor doesn’t act as a simple “up/down” check, but as a
value tracker: after each successful run it compares extracted (extractText) variables
with the previous successful run and sends a notification when any of them changed.
notifyOnChangeVars— JSON array of variable names to track. An empty array = track all extracted variables.
This lets you detect price changes, order status updates, or inventory levels on a page that is rendered only in the browser.
Statuses and pause
Section titled “Statuses and pause”A monitor is created with status pending and an initial check scheduled “now”. Then
it moves to up / down (and also degraded) based on run results.
You can pause and resume using the endpoints
POST /browser-workflow/:id/pause (status paused) and
POST /browser-workflow/:id/resume (returns to pending). While paused the workflow is not
run and no alerts are sent.
On failure the monitor card shows lastError and lastFailedStep — the text
of the last error and the name of the failing step.
REST API
Section titled “REST API”All endpoints require a client-token (where marked “write” — a token with write rights
or an MCP code with write access). In list responses encrypted cookies
are stripped out; instead a hasCookies flag is returned.
| Method & path | Authorization | Purpose |
|---|---|---|
GET /browser-workflow | client-token | list monitors (without cookies) |
POST /browser-workflow | client-token (write) | create a monitor |
PUT /browser-workflow/:id | client-token (write) | update a monitor |
DELETE /browser-workflow/:id | client-token (write) | delete a monitor |
POST /browser-workflow/:id/pause | client-token (write) | pause (status=paused) |
POST /browser-workflow/:id/resume | client-token (write) | resume (status=pending) |
POST /browser-workflow/build-step | client-token (write) | AI selection and verification of one step |
POST /browser-workflow/login | client-token (write) | run login and return session cookies |
POST /browser-workflow/test-step | client-token (write) | test run of the whole workflow |
Example: creating a monitor
Section titled “Example: creating a monitor”curl -X POST "$NOTIFLY_URL/browser-workflow" \ -H "X-Notifly-Key: C..." \ -H "Content-Type: application/json" \ -d '{ "appid": 12, "name": "Account balance", "startUrl": "https://app.example.com/dashboard", "steps": "[{\"name\":\"Wait for balance\",\"action\":\"waitFor\",\"selector\":\".balance-value\"},{\"name\":\"Remember balance\",\"action\":\"extractText\",\"selector\":\".balance-value\",\"extractName\":\"balance\"}]", "cookies": "[ /* plaintext cookies from /login */ ]", "intervalSec": 900, "timeoutSec": 60, "notifyOnChange": true, "alertMessage": "Workflow “Account balance” failed" }'See also: Active monitors · Content monitor · Workflow monitor (HTTP) · Full API.