Skip to content

Port scanning (discovery)

Port scanning (port discovery) answers the question “which TCP ports are open on this host at all?”. Notifly iterates over the specified port range, dials each port in parallel and collects a list of open ports. Unlike the port monitor, which continuously watches a known set of ports, a scan is a one-time (or periodic) inventory: you don’t yet know what is listening on the host and want to find out.

Typical flow: you start a scan → view the discovered ports → with one request turn the result into a continuous port monitor, which will alert if any of these ports suddenly closes.

create a scan task → status=pending
└─▶ Cloud Function port-monitor picks up the task
└─▶ advances the cursor over the range [rangeFrom..rangeTo] in batches
parallel TCP-dial with per-port timeout timeoutSec
open ports are accumulated into foundPorts (CSV) live
└─▶ reached rangeTo → status=completed, push with report
  • The scan is executed by a Notifly serverless function in Yandex Cloud, so the host must be reachable from the public internet (or from a YC private network).
  • cursor shows progress — the last scanned port; in the admin UI it shows what percentage of the range is already processed.
  • foundPorts (CSV of open ports) is accumulated live — partial results are visible before the scan completes.
  • On re-run, the previous result is saved in prevFoundPorts, allowing you to see a diff (appeared/disappeared ports).
  • Upon completion a standard Notifly push notification with a report is sent — via the channel (appid) you specified when creating the scan.

The port range can be set by a profile — a preset — or manually via rangeFrom/rangeTo. If the profile is not specified, it is chosen automatically: the full range 1–65535full, otherwise → quick.

profileWhat it scansPorts
quicknmap top-100 most common TCP ports100
standardports 1–1024 + popular ports above 1024~1080
fullthe whole range 1–6553565535
customarbitrary rangeFromrangeTo (default 1–65535)you set it

For custom the range is taken from your rangeFrom/rangeTo; for preset profiles the server will substitute the required ports and the provided range will be overridden.

  • name — task name, 1–200 characters (required).
  • appid — channel/application where the report will be sent (required).
  • host — hostname or IP (required), without / or spaces.
  • rangeFrom / rangeTo — range bounds, each in [1, 65535], rangeFrom ≤ rangeTo. Defaults are 1 and 65535.
  • timeoutSec — per-port TCP-dial timeout, default 2, maximum 10.
  • repeatIntervalSec0 = one-time scan; > 0 = repeat every N seconds, minimum 3600 (1 hour).
  • alertTitle / alertMessage / alertMessageMarkdown / alertPriority — push report styling; alertPriority in [0, 10].

The number of scan tasks per day is limited by your plan (portScansPerDay). When the daily counter is exhausted, creating a new scan returns 429:

PlanScans per day
Free10
Pro100
Business1000

More about quotas and tariffs — Quotas and tariffs.

  1. Open app.notifly.ruMonitorsPort scanning.
  2. Click “Scan host”, fill in the name, host, profile (or manual range), timeout and the channel for the report.
  3. Start it — progress (cursor) and discovered ports (foundPorts) update in real time.
Окно терминала
# Quick scan (top-100 ports), one-time
curl -X POST "$NOTIFLY_URL/port-scan" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <client-token>" \
-d '{
"appid": 12345,
"name": "Инвентаризация prod-хоста",
"host": "prod.example.com",
"profile": "quick",
"timeoutSec": 2,
"alertTitle": "Скан завершён",
"alertMessage": "Найдены открытые порты на prod.example.com",
"alertPriority": 5
}'
Окно терминала
# Custom range, repeat daily
curl -X POST "$NOTIFLY_URL/port-scan" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <client-token>" \
-d '{
"appid": 12345,
"name": "Веб-порты db-хоста",
"host": "db.internal",
"profile": "custom",
"rangeFrom": 8000,
"rangeTo": 9000,
"timeoutSec": 3,
"repeatIntervalSec": 86400,
"alertMessage": "Диапазон 8000–9000 на db.internal просканирован"
}'

The response is the created scan object with status: "pending", cursor, foundPorts (still empty) and an assigned id.

Окно терминала
# List all scan tasks
curl "$NOTIFLY_URL/port-scan" -H "X-Notifly-Key: <client-token>"
# One scan — progress and found ports
curl "$NOTIFLY_URL/port-scan/777" -H "X-Notifly-Key: <client-token>"

In the response look at status (pendingrunningcompleted/failed/cancelled), cursor (how far it reached), foundPorts (CSV of open ports) and prevFoundPorts (result of the previous run for diff). On failed the reason is in lastError.

Окно терминала
# Cancel a not-yet-completed scan (pending/running)
curl -X POST "$NOTIFLY_URL/port-scan/777/cancel" \
-H "X-Notifly-Key: <client-token>"
# Restart a completed/cancelled/failed scan
curl -X POST "$NOTIFLY_URL/port-scan/777/restart" \
-H "X-Notifly-Key: <client-token>"
  • Cancel is available only for an active scan; you cannot cancel a scan that is already completed/cancelled (400).
  • Restart is available for a completed scan: the previous foundPorts moves to prevFoundPorts, cursor is reset, and the scan starts again. If the scan is still active (running/pending) — cancel it first (400); if there is already another scan for the same host — 409.
  • Editing scan settings (PATCH) is allowed only while it is not in running status.

The main feature of discovery: a completed scan can be turned with one request into a continuous port monitor. The discovered ports (foundPorts) become the expectedPorts of the new monitor in closed mode — it will alert if any of the detected ports closes.

Окно терминала
curl -X POST "$NOTIFLY_URL/port-scan/777/to-monitor" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <client-token>" \
-d '{
"name": "Порты prod.example.com",
"intervalSec": 300,
"timeoutSec": 5,
"alertTitle": "Port alert: prod.example.com",
"alertMessage": "Закрылся ожидаемый порт на prod.example.com",
"alertPriority": 7
}'

The request body is optional — every field has a default: name = Monitor <host>, intervalSec = 300, timeoutSec = 5, alertTitle = Port alert: <host>, alertMessage = Port closed on <host>. The monitor inherits appid and host from the original scan.

Restrictions:

  • The scan must be completed (otherwise 400).
  • The scan must have discovered open ports — an empty foundPorts will give 400.
  • There must not already be an active port monitor for the host — otherwise 409.

All endpoints require a client token (or an MCP token with write permission); Basic Auth is also accepted.

MethodPathDescription
GET/port-scanList of the user’s scan tasks
GET/port-scan/:idOne scan: status, progress (cursor), foundPorts
POST/port-scanCreate a scan (429 when daily quota exceeded or 24h cooldown for full scan; 409 if a scan for the host is already running)
PATCH/port-scan/:idModify settings (not allowed for a running scan)
DELETE/port-scan/:idDelete a scan task
POST/port-scan/:id/cancelCancel an active (pending/running) scan
POST/port-scan/:id/restartRestart a completed scan
POST/port-scan/:id/to-monitorCreate a port monitor from the discovered ports