The symptom
You write a query, test it in overpass turbo, paste it into a script, run the script locally, and get data. You deploy the script and it fails. Nothing in the query changed, so the first hour usually goes on the query, and the query is not the problem.
Where it fails tells you nothing on its own, because the failing run is usually different from the working run in two ways at once: it is on a different network, and it is often using a different HTTP client. The public servers react to both. So the job is to separate the two, and the status code does most of that work for you.
Three causes, three status codes
| You get | What it means | Fix |
|---|---|---|
406 Not Acceptable |
Your client is manually blocked, almost always by its User-Agent string. | Send a descriptive User-Agent with a contact address. |
429 Too Many Requests |
The per-IP slot limiter. Cloud egress IPs are shared, so you inherit other tenants' usage. | Back off 30 s, serialise queries, or move off the shared IP. |
| Connection never completes, or 406 with a good User-Agent | Your network or client is banned: cloud ranges (parts of AWS and Azure), app-deployment platforms, or a client that kept retrying into 406s. | Run from a different network, your own instance, or a keyed instance. |
Everything below was checked against the live servers on 2026-09-11 from two places: a residential connection and a virtual server at a European hosting provider. We did not have an AWS or Azure address to test from, and we say so where it matters.
Cause one: 406 means your User-Agent is blocked
This is the case that catches most people, and it has nothing to do with where
you are running. The main public instance at overpass-api.de sits
behind an Apache front end, and since 2026-04-19 that front end refuses
requests whose User-Agent is missing or is a library default. The Overpass
software itself never emits a 406; its source only produces 200, 400, 429 and
504. A 406 is the operators' front door, not the query engine.
The operator who runs the front end explained the choice on the OSM community forum on 2026-04-25: "406 was a simple practical (and yes, slightly tongue-in-cheek) choice. I required an error code that is not produced by any other means to be able to identify the manually blocked users," adding that "the blocks for stock UAs will become permanent." Four days earlier the same operator noted that opening an interpreter URL directly in a browser "will still be blocked," and that the QGIS User-Agent had been excluded from the block after users reported breakage.
We sent the same one-node query to overpass-api.de with a range
of User-Agent strings. The result did not depend on the network: the
residential connection and the hosting-provider server got identical answers.
| User-Agent sent | Response |
|---|---|
| none at all | 406 |
python-requests/2.32.3 (the requests default) | 406 |
Python-urllib/3.12 (urllib and overpy) | 406 |
python-httpx/0.27.0 | 406 |
aiohttp/3.9.5 | 406 |
Go-http-client/1.1 | 406 |
node and axios/1.7.2 | 406 |
okhttp/4.12.0 | 406 |
| a real Chrome browser string | 406 |
Java/17.0.2 | 200 |
curl/8.14.1, Wget/1.21, PostmanRuntime/7.39.0 | 200 |
OSMnx Python package (https://github.com/gboeing/osmnx) | 200 |
my-osm-tool/1.0 (hello@example.com) | 200 |
The list is not "libraries bad, tools good": curl, Wget and Java's default client passed, while a genuine Chrome string failed because direct browser access to the interpreter is blocked on purpose. The pattern is that the operators block the identifiers they have seen abused. Treat any stock identifier as unsafe and send your own.
The 406 body is Apache's generic page ("An appropriate representation of the
requested resource could not be found on this server"), which explains nothing
and sends people off to check their Accept headers. The
Accept and Accept-Encoding headers made no
difference in our tests; only the User-Agent did.
This is why "works on my laptop" is so often true: the laptop run was overpass turbo or curl, which send a User-Agent the server accepts, and the deployed run is a Python script using the requests default, which it does not.
The fix
Send a User-Agent that names your project and gives a way to reach you. The main instance's usage policy asks for exactly that, a User-Agent or Referer header, so the operators can contact a misbehaving client instead of blocking its whole network.
import requests
HEADERS = {"User-Agent": "my-osm-tool/1.0 (hello@example.com)"}
r = requests.post(
"https://overpass-api.de/api/interpreter",
data={"data": query},
headers=HEADERS,
timeout=60,
)
r.raise_for_status()
osmnx already sets its own descriptive User-Agent, which is why osmnx users rarely see this. If you use overpy, urllib, httpx or aiohttp, set the header yourself. Do not borrow a browser's User-Agent string to get past the check: the check exists so the operators can identify clients, and spoofing it is the behaviour that gets a network range blocked instead.
Cause two: 429 means the IP limiter, and cloud IPs are shared
The public servers limit work per IP address: a small number of concurrent slots, a queue, and a cooldown once you have used your share. The 429 post covers the mechanics. What changes on a server is who else is behind your IP.
A laptop on a home connection has an IP address to itself. A Lambda function,
a container behind a NAT gateway, or a CI runner shares its egress address
with whatever else the platform puts behind it, and the limiter cannot tell
you apart. If another tenant on the same address is hammering Overpass, you
get their 429s. You can see your own standing with /api/status
from the server in question; if it reports slots in use you never started,
that is the shared IP.
The operators tightened this in August 2026: clients that repeatedly run into
a 429 or 406 are banned faster, and applications with a high rate of 429s are
banned as applications. Wait at least 30 seconds after a 429 before the next
query; with curl that means --retry-delay 30, because curl's
default retry delay is far shorter than the server's cooldown.
Cause three: your whole network range is blocked
This is the one people assume first and it is the least common. On 2025-10-13 the Overpass author announced on the community forum that parts of Azure and AWS would be blocked for a while, because "someone is rather smart in free-riding the public instances from the cloud instead of simply setting up a cloud instance": one party was spreading its load across thousands of cloud addresses to stay under the per-IP limiter. The announced window was eight weeks. The thread records no lifting of the block; its last reply, in January 2026, is a complaint that the main instance had become hard to use at all.
On 2026-08-11 the front-end operator added that "many platforms for fast-deployment of AI-generated apps like lovable.app or netlify.app" are now banned outright, after a wave of retry loops from apps generated on those platforms. The main instance's usage policy on the OSM wiki now says the same.
Two things we can say from our own testing. First, "datacentre IP" is not the rule: our test server at a European hosting provider was not blocked on any of the three public instances we tried, with a proper User-Agent. Second, we could not test from an AWS or Azure address, so we cannot tell you exactly what those ranges receive today. What we can tell you is what a ban looks like, because we earned one while writing this.
What a ban looks like, observed
To build the table above we sent requests with blocked User-Agents from each
network, a few seconds apart. Each one returned a 406. On the residential
connection it took six of them.
The operators had said in August that clients which repeatedly run into a 429
or 406 are banned faster, and they meant it. Within minutes, the residential
connection stopped being able to open a TCP connection to
overpass-api.de at all: no status code, no error page, every
request timing out, while every other host, including other Overpass
instances, answered normally. The hosting-provider server hit a short spell
where even the good User-Agent got a 406, then recovered within two minutes.
So the signature of a network-level block is a connection that never completes, and the signature of a client-level block is a 406 that survives a good User-Agent. Neither comes with an explanation, and the fastest way to get one is to keep retrying the request that caused it. We stopped testing at that point, which is also the advice.
Telling them apart in two minutes
-
Send the same request from the failing machine with a descriptive
User-Agent. If it now works, it was cause one. Most cases end here.
shell
curl -sS -o /dev/null -w '%{http_code}\n' \ -A 'my-osm-tool/1.0 (hello@example.com)' \ --data-urlencode 'data=[out:json][timeout:10];node(52.52,13.40,52.521,13.401);out 1;' \ https://overpass-api.de/api/interpreter -
If you get a 429, read
/api/statusfrom the same machine. Slots in use that you did not start mean a shared address. Serialise your queries, wait out the cooldown it reports, and consider that the address may never be quiet. - If a 406 or a dead connection survives step one, it is the network. Confirm by running the identical curl from any other network. Do not reach for a proxy.
Your options, honestly
Fix the client. A descriptive User-Agent, one query at a time, a 30-second back-off on 429, and caching of anything you ask for twice. For an occasional job this is all you need, and it is what the public servers ask of everyone.
Run the job somewhere the public servers can see. A machine with its own address at a hosting provider, or a scheduled task on a workstation, has none of the shared-IP problems. It is also the honest place for a job that only runs once a day.
Run your own instance. Full control, no limits beyond your hardware, and the operators of the public servers will thank you. It is real work: a full planet is hundreds of gigabytes, takes days to import, and needs its update loop watched.
Use a keyed instance. On a keyed server the key is the identity, not the IP address and not the User-Agent, so the same script runs from a laptop, a Lambda, or a CI runner without changing anything but the URL. We run one, Overspan: with no key or a bad key it answers 401 whatever User-Agent you send, and with a valid key it answers from any network. The neutral list of every public and commercial instance is the OSM wiki's instances table.
What not to do
Do not rotate proxies, spoof browser User-Agents, or spread a job across addresses to stay under the limiter. That is precisely the behaviour that caused the cloud-range blocks in the first place, and it makes the public servers worse for every volunteer-funded user who is doing the right thing. If your job has outgrown the free pool, the answer is to leave the free pool, not to hide in it.
Sources: the 406 and User-Agent behaviour was reproduced against
overpass-api.de on 2026-09-11 from two networks; operator
statements are quoted from the OSM community forum threads
"Overpass API will block Azure and AWS for some time"
(2025-10-13) and
"Overpass API performance issues"
(posts of 2026-04-21, 2026-04-25 and 2026-08-11), and from the
main instance's usage policy
on the OSM wiki. If the servers change their behaviour, mail
hello@overspan.dev and we will fix the post.