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:
exclude_locations— a list of points. Each gets snapped to the nearest road(s), and those roads are dropped from consideration entirely. Cheap and fast. This is the natural fit for point-like things such as a camera at an intersection.exclude_polygons— areas to route around; any road crossing the polygon is excluded. Heavier, but useful for "stay out of this whole corridor."
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:
exclude_locationsis a hard exclusion — those roads are gone, full stop. If a camera sits on the only road to the destination, the route fails rather than reluctantly using it. Per-edge soft penalties (use the road, but only if the detour isn't absurd) aren't a first-class API feature yet — there's an open request for it — so for graceful degradation you'll lean on custom costing in a self-hosted build, or fall back to the unrestricted route.exclude_polygonsis slower thanexclude_locations, and has edge cases — e.g. if both endpoints sit inside a polygon, the result can still run through it. Prefer points where you can.- Your route is only as good as your camera data. Keeping coordinates fresh is the real ongoing work, not the routing.
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.