Warning: session_name(): Session name cannot be changed after headers have already been sent in /var/www/html/includes/header.php on line 12
← All posts
Blog

Why we route around surveillance with Valhalla

Shout-out: Valhalla

If you're building anything that puts a line on a map between point A and point B, you eventually hit the same wall: the easy routing APIs (Google, Mapbox Directions, etc.) are black boxes. You send coordinates, you get a polyline, and you have basically zero say over why it chose that road. That's fine for "get me to the airport." It's useless the moment you need the route to respect a constraint the provider never thought about.

For us, that constraint is automated license plate readers — specifically the Flock Safety camera network that's quietly blanketed a huge number of US roads. We wanted routing that treats those cameras as something to avoid, so a trip can get from A to B without feeding a passive surveillance dataset. No off-the-shelf API exposes "don't drive past the ALPR on 5th and Main." Valhalla does.

What Valhalla actually is

Valhalla is an open-source routing engine built on OpenStreetMap data, MIT-licensed, ~5.8k stars, actively maintained (3.7.0 dropped in April 2026). Beyond plain A-to-B routing it also does isochrones, time/distance matrices, map matching, elevation, and tour optimization. It ships with Python (pyvalhalla) and Node (@valhallajs/valhallajs) bindings and a Docker image, so you can self-host a planet graph or a regional extract without much ceremony.

Why it's the right tool for this

A few of its design choices line up almost suspiciously well with a "route around X" problem:

Dynamic, runtime costing. This is the headline feature. Valhalla doesn't bake routing decisions into the graph at build time — you pass costing rules per request. That means you can change how the engine feels about a road on every single query without rebuilding anything. Exactly what you want when your avoid-set is a live, changing list of camera coordinates.

Built-in exclusion parameters. Two come straight out of the box:

You self-host it, so the routes stay yours. This is the part that matters most for a privacy app and is easy to overlook. With a hosted directions API, every route request — every origin, destination, and the fact that someone wants to dodge cameras — goes to a third party. With Valhalla on your own infrastructure, the camera dataset and the user's trips never leave your stack. Avoiding surveillance via a service that surveils you would be a bad joke.

Tiled + offline + mobile. The graph is a tiled, hierarchical structure with a small memory footprint, and the C++ core cross-compiles to iOS and Android. So this can eventually run on-device, fully offline — no network round-trip at all.

What it looks like

A camera-avoiding auto route is basically a normal route request with your camera points dropped into exclude_locations:

{
  "locations": [
    { "lat": 36.1699, "lon": -115.1398 },
    { "lat": 36.1147, "lon": -115.1728 }
  ],
  "costing": "auto",
  "exclude_locations": [
    { "lat": 36.1402, "lon": -115.1501 },
    { "lat": 36.1305, "lon": -115.1622 }
  ]
}

Maintain the camera list as a dataset, filter it to a bounding box around the trip, and inject the points at request time. Done.

Honest caveats

It's not pure magic, so a few things to keep in mind:

Bottom line

The combination — open data, runtime costing, real exclusion parameters, and the ability to run the whole thing yourself — is why Valhalla beats every hosted directions API for this. It's the difference between asking someone else to route you and owning the routing logic outright. For a tool whose entire premise is "don't be tracked," that ownership isn't a nice-to-have. It's the point.