SparrowMap · how it works
Volunteers point cameras at public roads, and everything they see goes into one shared database that anyone can read — no account, no login, no permission. Recognition happens on the contributor’s own machine, so no video is ever uploaded. A person confirms anything before it is published as a government vehicle. Everything else becomes an anonymous dot that fades in forty-five seconds and is deleted in fourteen days.
The same technology is normally sold to police departments and kept private — you cannot see it, query it, or know you are in it. SparrowMap runs one shared database, and every sighting in it is readable by anyone, including the people it watches. There is no customer tier, no paid access, and no version of this map with more in it than the one you are looking at.
Three kinds of machine, each allowed to hold a different amount. The split is the security design, not an accident of deployment.
The box is deliberately the low-value target. Breaking into it yields the published record — which is already published. The things worth stealing live on a machine that does not accept connections from the internet at all.
Note what this list does not contain: a position. /api/nodes
publishes no coordinates at all — not the true ones, not the blurred
ones, not even the heading or field of view, because an aim vector would let
you work backwards from the road to the window. Only the stretch of road is
public.
This is the common case, and the case the whole system is built around. It happens thousands of times a day and it must produce no record of anybody.
One thread reads the camera as fast as frames arrive and overwrites a single slot. Whatever was there is discarded unread.
That sounds wasteful and it was measured instead of assumed: the stream delivered 20 fps while the detector consumed 4.3, and every read was returning a backlogged frame. A vehicle reported four seconds late at the wrong point on the road is a false record; a vehicle missed is just a vehicle.
A detector finds the vehicle and a tracker follows it across frames. The pass is emitted when the car has been gone for twelve frames, and only if it was seen in at least three — which kills the one-frame flickers that would otherwise each become a “sighting”.
Every plate-shaped region is pixelated and then painted over with an opaque bar labelled PLATE NOT STORED. Pixelation alone is reversible on a fixed-layout character set — you can render every candidate, downsample, and compare — so the bar is what actually destroys it and the pixelation is what survives if the bar is ever removed.
This step is skipped for a government vehicle, and
that is deliberate rather than an oversight: its snapshot is the public
record, and a public record of a patrol car with the plate painted out
would prove nothing. The redaction is gated on the tier
(snapshot.py), so it runs for everybody else.
Every candidate region is redacted, not just the best one. On a marked vehicle the door lettering is a bigger patch of white-on-dark than the plate, so “the biggest one” blacked out the livery and left the plate readable.
The vehicle is segmented out and everything else — houses, porches, other cars, people on the pavement — is replaced with flat grey.
Blur was considered and rejected. A blurred building is still a building of that shape, in that place, at that angle, and deblurring is an active research field with working tools. The threat is specific: a subject of the map working out which window is photographing them.
A structured claim and one cropped still. No video — and not because of a policy, but because a stream is never created. There is nothing to intercept, subpoena or leak.
No light bar, no decals, nothing. The vehicle is classified civilian, so it enters the private tier.
Because it is private and there is no plate region to redact, the image is discarded entirely. The sighting still counts; only the photograph goes.
The coordinates stored are a point along the published stretch of road, derived deterministically so the dot never jumps — and so nobody can average many readings back to the middle.
This was a real bug once. Sightings were stored at the camera's true coordinates, which made the blurring on the camera list worthless. It was caught because a camera marker and its own sightings sat 57 metres apart.
Plate text, plate state, plate hash, plate confidence, photo, training reference, make, model, colour, body, heading, speed. Reduction happens on the way in, never on the way out — a read-time filter leaves the data on the disk, and the disk is what gets copied.
fetching…
This is fetched live from the public API as you load this page.
node_id is a rolling identifier that changes every day, so a
dot cannot be traced back to whose camera saw it — nor can one
person's cameras be grouped together and profiled.A grey dot, on a road, at a time. It fades from the map in 45 seconds, the row is deleted in 14 days, and the hashing key rotates every 30 — so even the identifier it never had would have stopped meaning anything.
The rare case. Roughly ten a day against several thousand ordinary passes — and the only case where anything is published.
A machine's opinion alone cannot publish a vehicle. Calling something police requires two distinct visual markers on the vehicle itself — a roof light bar and door decals, say — or a human who has looked at it.
| Decision | Bar | What it permits |
|---|---|---|
| a public dot | conf ≥ 0.60 | “a marked patrol unit was here” — no identifier at all |
| the plate text (government only) | conf ≥ 0.85 | a government plate may be stored, and searched once a person confirms it |
The identifier always costs more evidence than the dot. That asymmetry is the whole two-tier design in one line.
A government candidate is shrunk to a thumbnail too small to read a plate from and parked in a review pen. The row stays private. Nothing has been published yet.
A reviewer sees one crop at a time and answers: cop, or not a cop. Confirming promotes the row and attaches the crop as its photo. Rejecting drops the crop and leaves the row private — and that rejection is the most valuable training data the project gets, because it is a hard negative in exactly the conditions the model fails in.
Every verdict is written to a public audit log under the reviewer's name, and every verdict can be reversed.
review:confirm 30543 actor=Matthew review:reject 30761 actor=Matthew review:confirm 31656 actor=Matthew
Real rows from the audit log. Fifteen candidates were worked by hand the night this page was written.
The map is young. These are the honest limits of what it can claim today, so nothing here is taken for more than it is.
SparrowMap does keep plate text — but only for a government vehicle, and only after a person has confirmed it. An ordinary vehicle’s plate is destroyed in the image on the camera and never stored readable, so there is nothing to look up and no way to search for one.
In practice the plate half is still unproven. Reading a plate needs far more detail than recognising a patrol car does, and the current camera does not resolve enough of one at the distance it watches. That is a lens problem, not a software one. Until better optics are in place, treat the map as “a marked patrol unit was here” — which is the useful part anyway.
The in-browser detector is deliberately tiny so it runs on an old phone. It can find a vehicle and send a plate-illegible crop, but deciding whether something is a government vehicle takes models that only run on a desktop machine. So a phone contributes evidence, and a desktop and a person make the call.
Recognising a marked patrol car from a window, at an angle, in motion, is genuinely hard, and the classifier is sometimes wrong in both directions. That is precisely why nothing reaches the map on a machine’s say-so: a candidate waits in a review pen for a human, every decision is logged under a name, and any decision can be taken back.
A tap from a passing driver is a crowd signal, not a measurement. They are shown in a different colour, they expire on their own, and they never join the permanent record.
A moving phone works out roughly where a vehicle sat relative to the car, from its size and position in frame. It is an estimate, not a survey, and it is treated as one.
An empty area on the map means nobody is watching it, not that nothing happened there. The map only ever shows what a real camera actually saw.
A promise you can only take on trust is a slogan. Each of these is enforced somewhere specific, and most can be verified from outside without asking anyone's permission.
Enforced by architecture, not policy. Recognition runs on the contributor's machine; what crosses the network is a claim and one crop.
Check it — the policy endpoint below reports
stores_video: false, and it is a statement about a thing that is
never created.
Pixelated and barred in the image, before anything is stored, over every plate-shaped region rather than only the largest.
Check it — the live private row in section 02 has no plate, no hash, and no photograph.
Cameras publish the stretch of road they watch. The camera list carries no coordinates at all, and sightings are placed along the road rather than at the lens.
Check it — read /api/nodes yourself.
There is no position field to remove.
Looking up a public record is nobody's business but the reader's. A search history would be a chilling record of who asked a question — the exact posture this project refuses.
Check it — the public audit log contains operator decisions only. Searches never appear in it, because they are never written.
The web server in front of the map discards its access log and strips the forwarded-address header, so the application never learns a visitor's IP even if a future code path wanted it.
Check it — the configuration is two lines in the public repository.
A classifier call lands in a review pen. A human confirms it. The verdict is logged under their name and can be reversed.
Check it — the audit log is public, and every published sighting shows the reasoning that put it there.
Every core module on the live server is byte-for-byte identical to the public repository. Nothing special runs in production.
Check it — clone the repository and compare. The licence is AGPL: run your own instance.
These values come from the server as you load this page — not from this document. An outsider can read the same endpoint and diff it against what is claimed here, which is the point of publishing it at all.
Private passes are counted and never identified. That ratio — a few public sightings against thousands of anonymous passes — is the design working as intended.
Everything above is checkable. That is deliberate: the project's credibility rests on being verifiable rather than on being confident.
The database is not behind a login, an account or a contract. Any of these answers from the live server, in a browser or from a terminal, with no permission from anyone:
curl https://map.sparrowmap.com/api/sightings # every sighting on the map
curl https://map.sparrowmap.com/api/nodes # every contributing camera
curl https://map.sparrowmap.com/api/policy # what this deployment promises
curl https://map.sparrowmap.com/api/audit # what the reviewers decidedThat is the difference worth caring about. The same cameras, pointed at the same streets, normally feed a private database sold to police departments — one you cannot query, audit, or opt out of. This one answers to anybody who asks.
Found something wrong — a vehicle classified incorrectly, a number that does not add up, a claim on this page the code does not support? That is the most useful thing you can send. Report it in the open, or write to [email protected].