Guide

Overpass API errors explained

What 400, 429 and 504 mean, why a query can fail with HTTP 200, and how to fix each error. With retry code for Python and JavaScript.

You seeMeaningFix
400 Bad RequestThe query has a syntax error.Read the error line; check quotes, semicolons and Overpass Turbo shortcuts.
429 Too Many RequestsRate limit: too many queries at once or in a row.Wait, then retry with back-off. Send queries one at a time.
504 Gateway TimeoutThe server is too busy to accept the query.Retry later; ask for less time and memory.
runtime error: Query timed outThe query ran longer than its [timeout:].Narrow the search or raise the timeout.
runtime error: Query run out of memoryThe answer needs more than [maxsize:].Smaller area, leaner output, or raise maxsize.
Empty resultNothing matched.Check the area name, admin_level, tags and output statement.

400 Bad Request: syntax errors

The server could not parse the query. The response is an HTML page with lines like Error: line 2: parse error: ';' expected - ')' found. The line number points to the problem.

  • Overpass Turbo shortcuts. {{bbox}}, {{geocodeArea:Paris}} and {{center}} are expanded by Overpass Turbo only. In your own code, replace them with coordinates or an area query. This is the most common cause.
  • Quotes. Values with spaces, colons or special characters need double quotes: ["addr:street"="Main Street"]. Curly quotes copied from a word processor don't work.
  • Missing semicolons at the end of a statement, or a missing out;.
  • Coordinates in the wrong order. A bounding box is south, west, north, east. Swapped values are no syntax error but return nothing.

429 Too Many Requests

A rate limit was hit. On the public overpass-api.de it means all slots of your IP address are busy; see “Too Many Requests” on overpass-api.de for how the slots work.

On overpass.ch, the JSON body says which limit you hit (rate_limited, concurrency_limit or quota_exceeded), and the Retry-After header says how many seconds to wait. See the error reference.

504 Gateway Timeout

The message “The server is probably too busy to handle your request” means the query was not even started. Overpass admits queries based on the run time and memory they ask for ([timeout:] and [maxsize:]). When the server is busy, big requests are turned away first.

  • Ask only for what you need: [timeout:25] instead of [timeout:900].
  • Retry after a pause, with back-off (code below).
  • If it happens at all hours, the server is overloaded. A server with reserved capacity solves it; paid plans on overpass.ch are served first.

“runtime error: Query timed out”

Careful: this error arrives with HTTP 200. With JSON output, the message is in the remark field and elements may be empty or incomplete. Always check remark in your code.

{
  "elements": [],
  "remark": "runtime error: Query timed out in \"query\" at line 3 after 26 seconds."
}
  • Put the most selective filter first, and always restrict by area or bounding box.
  • Avoid regular expressions on keys over large regions ([~"."~"."]).
  • Raise the timeout within your limits: [timeout:120].
  • Split big regions into parts, or use out count if you only need numbers.

“runtime error: Query run out of memory”

The answer would need more memory than allowed (512 MiB by default). Also delivered with HTTP 200 and a remark.

  • Use leaner output: out center; or out tags; instead of out geom;, and out skel; when you need no tags.
  • Search a smaller area, or split it.
  • Raise the limit: [maxsize:1073741824] (1 GiB), within your plan.

Empty results

  • Wrong area. area["name"="…"] matches the exact name in the local language, and many places share a name. Add the right admin_level; is_in shows the levels at a point. For Lisbon, for example, the municipality is level 7, not 8.
  • Only nodes searched. Many shops and most parks are ways. Use nwr and out center;.
  • Ways without coordinates. out; on ways returns node IDs only. Use out geom; or (._;>;); out;.
  • Tags spelled differently. Check the tag on the OpenStreetMap wiki or on a known example in the map.

Retry code

Retry only errors that can go away (429, 503, 504), wait longer each time, and honour Retry-After when the server sends it. Check remark on every successful answer.

import time, requests

URL = "https://api.overpass.ch/v1/YOUR_API_KEY/interpreter"

def overpass(query, tries=5):
    wait = 10
    for _ in range(tries):
        r = requests.post(URL, data={"data": query}, timeout=300)
        if r.status_code in (429, 503, 504):
            time.sleep(int(r.headers.get("Retry-After", wait)))
            wait *= 2
            continue
        r.raise_for_status()
        data = r.json()
        if "remark" in data:  # timeouts and memory errors come with HTTP 200
            raise RuntimeError(data["remark"])
        return data["elements"]
    raise RuntimeError("Overpass is busy, giving up")

Replace the URL with https://overpass-api.de/api/interpreter for the public server.

Tired of 429 and 504?

overpass.ch runs the same Overpass API with full-planet data, minutely updates and limits per API key. Paid plans are served first.