SanAlert

Unofficial service. It does not replace sirens, RCB alerts or instructions from the authorities.

Track record

We compare our levels with the official RCB and RSO warnings: before a voivodeship was warned, was SanAlert already showing something there, and how often did we raise a level with no official message at all? We compute it every night from a recording of everything the sources said.

The numbers are small and the period short. We have been recording since 18 September 2026; one warning more or less changes everything here. RCB and RSO are not the only truth either: an official warning can come late or not at all, and a rise without one does not prove we were wrong.

Loading the record…

How we count

Our levels
We do not log them as they happen; we replay them. Our recorder keeps every answer the sources gave, with the time we received it. Every night we feed those answers, in order, through the same model that computes the levels on the website and in the app. A voivodeship's level is the highest level among its squares. When we change the model, we recompute the whole period.
Official warning
An RCB alert or an RSO message about a threat from the air that we saw live, to the minute. The same alert on RCB's website and in RSO counts once, from the moment we first saw it. An alert sent again while the earlier one is still in force counts once too. Exercises and cancellations do not count. Alerts from before the recording began are known only by their date, so they cannot be compared.
Ahead, late, not raised
For each voivodeship a warning covered, we check whether SanAlert was showing at least Activity there. Ahead: the level was already raised when the warning came. Late: we raised it within an hour after. Not raised: not within that hour. No data: we had no data when the warning came. The same is given for Approaching. Gaps shorter than 10 minutes do not break a raised level.
Rise with no official message
At least Approaching for at least 10 minutes in a voivodeship with no official message about a threat from the air from an hour before to an hour after. Shorter rises are counted separately.
No data
Time in which the website would have shown No data, because the source of tracked objects had not answered for more than 3 minutes. It comes from the recording, so a gap in the recorder itself counts too.

Changes to the model and the record

What we changed in how the levels and this record are worked out, newest first. The date is the day the change reached the site.

  1. : Model: no widening for a presumed course in “Near” on course

    When NEPTUN only presumes where an object is heading, we widen the corridor around its course by 20 km. That stays for “Approaching”. It no longer applies to “Near” on course: on the night of 1 November a drone that NEPTUN placed on a course for Lviv gave “Near” in a square 54 km to the side of its course.

    Effect: “Near” on course now comes only when the object would pass within about 30 km of the square. Replayed over the 47 days since 18 September, 92 squares were ever “Near” instead of 96, and the lead before RCB and RSO messages did not change. The reliability record and the night reports are recomputed from scratch.

    API 0.26.5

  2. : Record: two messages that were not warnings

    The record counted two messages as warnings of a threat from the air that were not. An RCB alert about a shop fire in Silesia (7 October) read as an air-threat message because the shop's name contains the word “dron”; we also showed it on the map and posted it. An RCB alert of 30 September we first saw on the morning of 1 October, when RCB published it late after its website failed; we counted it as a warning of that morning.

    Effect: Both leave the record: since 18 September, 45 warnings instead of 47, and “not raised” in 1 voivodeship instead of 3. A fire and messages like it are no longer shown as a threat from the air.

    API 0.26.5

  3. : Model: no “Near” from distant, stale positions

    When we work out “Near”, we add an object's position uncertainty to the radius (about 25 km) and to the corridor around its course, but now at most 10 km of it. NEPTUN raises that uncertainty as a position grows old, up to over 60 km. Added in full, it let a drone last placed at Lutsk, over 80 km from the border, give “Near” in Poland. That happened on the night of 19 to 20 October.

    Effect: “Near” comes less often: only when the object may be close by. A drone whose position is very uncertain gives a lower level. The reliability record and the night reports are recomputed from scratch. The lead before RCB messages is measured from “Activity”; replayed over the 32 nights since 18 September, it did not change.

    API 0.26.0

  4. : Model: each object says which level it raises

    For every drone and missile the model now records the highest level that object raises in any square right now. The map colours objects by it, so you can see which object gives which level. An object that raises no level in Poland is drawn grey or white, not in a level's colour.

    Effect: The levels are computed exactly as before, so none changed. The model's fingerprint changed, so the reliability record and the night reports are recomputed from scratch; their results stay the same.

    API 0.25.0

  5. : Grid: 72 squares outside Poland removed

    The grid's margin, meant for squares on the border, also took in 72 squares wholly outside Poland, among them in Volyn beyond the Bug. The map never showed them, yet they could raise “SanAlert's highest level now”. Only squares with some of Poland in them remain.

    Effect: No place in Poland lies in those squares, so the level of no place changed. A voivodeship's level no longer rises from squares outside Poland. We recomputed the reliability record and the night reports from scratch.

    API 0.20.3

  6. : Model: movement over the last 15 minutes, lost tracks, “No data” when the source freezes

    Whether a drone is coming closer is judged from its positions over the last 15 minutes, not only from its last jump: a drone flying in small steps went from “Activity” straight to “Near”. An object that disappears from the source while it raised a square to “Approaching” or “Near” keeps that square at least at “Activity” for 30 minutes. When NEPTUN answers but its data stands still or cannot be read, we show “No data”. When the alarm feed from Ukraine goes silent, the levels lean on the last alarms for 30 minutes, then go on without them.

    Effect: We recomputed the record and the night reports from scratch. Since that day they replay the levels by the same rules as the site.

    API 0.20.0

  7. : Model: “Approaching” means about 30 minutes, and a drone seen coming closer

    “Approaching” needs an object that could arrive in about 30 minutes, and a drone has to be seen coming closer: a predicted course alone gives at most “Activity”. Before, a course was enough, often only a presumed one, worked out from sightings known to the nearest town.

    Effect: A review of the recording of 18–26.09: none of the 36 drones for which we showed “Approaching” came within 30 km of such a square or entered Poland. With the new rule, the squares' total time at “Approaching” over that period fell from 7,519 to 130 minutes, and the drones that caused it from 45 to 3. We recomputed the record and the reports from scratch.

    API 0.19.0

  8. : Record: an all-clear sent on its own ends a warning

    On 25.09 at 5:25 RSO sent the night's end as a message of its own (“Brak zagrożenia na terenie Polski”), not as a change to the alert. The record did not see the warning end, so it counted our rises after 0:43 as rises without an official message, though the alert still stood. Now RCB's and RSO's all-clears sent on their own end a warning too.

    Effect: The night of 24/25.09 is recomputed in the record and in its night report: the rises after 0:43 no longer count as without a message.

    API 0.16.1

  9. : Record: an alert sent again is not a new warning

    RCB sometimes sends the same alert again while it still stands (24.09 at 8:13, two hours after the first). We count it as the same warning, unless it names a new voivodeship or comes after the all-clear.

    Effect: None of the warnings so far changed.

    API 0.14.2

  10. : A public reliability record

    Every night we replay our levels from the recording of the sources kept since 18.09 and set them against the official RCB and RSO warnings.

    Effect: Since that day every change to the model means recomputing the whole period: the numbers on this page always come from the model in use today.

    API 0.6.0

  11. : Safer publishing of the levels

    When working out the levels failed, the server published the old levels with a fresh time. A NEPTUN answer without a list of objects looked like an empty sky, that is “Quiet”. Alarms from a feed that had gone silent still fed the levels. Now the first two cases show “No data”, and alarms from a silent feed are not used.

    Effect: Before the record existed. The record computes the whole period by today's rules.

    API 0.3.1

  12. : Alarms in Ukraine by raion

    We read only the list of oblasts with an alarm, so the rule “an alarm in a raion of Ukraine within about 100 km” could never fire. From this version we read the alarms per raion, with their kind (drones, missiles). A warning for a whole oblast with no position of an object gives at most “Activity”.

    Effect: Before the record existed. The record computes the whole period by today's rules.

    API 0.2.0

  13. : sanalert.pl goes live

    The first public version: levels for squares about 11 km across, worked out from the objects NEPTUN tracks, beside the RCB and RSO messages.

    API 0.1.0

Night by night, voivodeship by voivodeship: Night reports.

Details and the document with the numbers: api.sanalert.pl/v1/record.