Wikidata SPARQL 504: the 60-second ceiling and the query that works Checked 2026-09-08 · Wikipedia and Wikidata as data query.wikidata.org cuts a query off at about 60 seconds and answers HTTP 504 with the 24-byte plain-text body 'upstream request timeout'. It is not JSON, so a client that calls .json() on it raises a decode error instead of reporting the timeout. Chunking the same query by a date range brought it back in 13.6 seconds with 15,898 rows. Separately, the label service does not fail loudly: when an item has no label it returns the Q-number as the label value, and the tell is that the binding has no xml:lang key. What we saw An unbounded query over humans with birth dates and the label service times out at about 60 seconds with a 504 and a plain-text body. Source: https://query.wikidata.org/sparql (SELECT ?item ?itemLabel ?birth WHERE { ?item wdt:P31 wd:Q5 ; wdt:P569 ?birth . SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } }, 2026-09-08). HTTP 504 size=24, real 1m5.207s, body: upstream request timeout The 504 carries content-type text/plain and content-length 24, from an envoy front end. Source: https://query.wikidata.org/sparql (response headers, 2026-09-08). HTTP/2 504 / content-length: 24 / content-type: text/plain / date: Tue, 08 Sep 2026 05:07:06 GMT / server: envoy The same shape of query, bounded to a two-day birth-date window, returns in 13.6 seconds with 15,898 rows. Source: https://query.wikidata.org/sparql (SELECT ?item ?birth WHERE { ?item wdt:P31 wd:Q5 ; wdt:P569 ?birth . FILTER(?birth >= "1990-01-01T00:00:00Z"^^xsd:dateTime && ?birth < "1990-01-03T00:00:00Z"^^xsd:dateTime) }, 2026-09-08). HTTP 200 size=4478419, real 0m13.588s, bindings 15898 A LIMIT 100000 query with the label service does complete, at 59 seconds and 24 MB, so the ceiling is time and not row count. Source: https://query.wikidata.org/sparql (SELECT ?item ?itemLabel WHERE { ?item wdt:P31 wd:Q5 . SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } } LIMIT 100000, 2026-09-08). HTTP 200 size=23912053, real 0m59.187s 855 of those 100,000 rows came back with the Q-number as the label, and those bindings carry no xml:lang key while real labels do. Source: https://query.wikidata.org/sparql (results.bindings[].itemLabel, 2026-09-08). total 100000 label==QID 855 ; first 5: ['Q42', 'Q185', 'Q192', 'Q254', 'Q535'] ; bad binding: {'type': 'literal', 'value': 'Q42'} ; good binding: ('Q23', 'George Washington') with an xml:lang key That is a genuine absence, not a label-service bug: asking for the label directly returns no rows for the same item. Source: https://query.wikidata.org/sparql (SELECT ?l WHERE { wd:Q42 rdfs:label ?l FILTER(lang(?l)="en") }, 2026-09-08). { "head" : { "vars" : [ "l" ] }, "results" : { "bindings" : [ ] } } The command UA='fieldbook/1.0 (https://example.org; notes@example.org)'; time curl -sS -o t1.txt -w '\nHTTP %{http_code} size=%{size_download}\n' -m 180 -A "$UA" -G 'https://query.wikidata.org/sparql' --data-urlencode 'query=SELECT ?item ?itemLabel ?birth WHERE { ?item wdt:P31 wd:Q5 ; wdt:P569 ?birth . SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } }' -H 'Accept: application/sparql-results+json'; cat t1.txt HTTP 504 size=24 real 1m5.207s user 0m0.022s sys 0m0.018s upstream request timeout Checked 2026-09-08. curl -sS -D - -o /dev/null -A "$UA" -G 'https://query.wikidata.org/sparql' --data-urlencode 'query=SELECT ?item ?itemLabel ?birth WHERE { ?item wdt:P31 wd:Q5 ; wdt:P569 ?birth . SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } }' -H 'Accept: application/sparql-results+json' | head -5 HTTP/2 504 content-length: 24 content-type: text/plain date: Tue, 08 Sep 2026 05:07:06 GMT server: envoy Checked 2026-09-08. time curl -sS -o ok.json -w '\nHTTP %{http_code} size=%{size_download}\n' -m 120 -A "$UA" -G 'https://query.wikidata.org/sparql' --data-urlencode 'query=SELECT ?item ?birth WHERE { ?item wdt:P31 wd:Q5 ; wdt:P569 ?birth . FILTER(?birth >= "1990-01-01T00:00:00Z"^^xsd:dateTime && ?birth < "1990-01-03T00:00:00Z"^^xsd:dateTime) }' -H 'Accept: application/sparql-results+json'; python3 -c "import json; d=json.load(open('ok.json')); print('bindings', len(d['results']['bindings'])); print(d['results']['bindings'][0])" HTTP 200 size=4478419 real 0m13.588s bindings 15898 {'item': {'type': 'uri', 'value': 'http://www.wikidata.org/entity/Q4666329'}, 'birth': {'datatype': 'http://www.w3.org/2001/XMLSchema#dateTime', 'type': 'literal', 'value': '1990-01-01T00:00:00Z'}} Checked 2026-09-08. time curl -sS -o q1.txt -w '\nHTTP %{http_code} size=%{size_download}\n' -m 120 -A "$UA" -G 'https://query.wikidata.org/sparql' --data-urlencode 'query=SELECT ?item ?itemLabel WHERE { ?item wdt:P31 wd:Q5 . SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } } LIMIT 100000' -H 'Accept: application/sparql-results+json' HTTP 200 size=23912053 real 0m59.187s Checked 2026-09-08. python3 -c "import json,re; b=json.load(open('q1.txt'))['results']['bindings']; qid=re.compile(r'^Q\\d+$'); bad=[x for x in b if qid.match(x['itemLabel']['value'])]; print('total',len(b),'label==QID',len(bad)); print([x['item']['value'].split('/')[-1] for x in bad[:5]]); print(bad[0]['itemLabel']); good=[x for x in b if not qid.match(x['itemLabel']['value'])]; print([(x['item']['value'].split('/')[-1], x['itemLabel']['value']) for x in good[:3]])" total 100000 label==QID 855 ['Q42', 'Q185', 'Q192', 'Q254', 'Q535'] {'type': 'literal', 'value': 'Q42'} [('Q23', 'George Washington'), ('Q76', 'Barack Obama'), ('Q80', 'Tim Berners-Lee')] Checked 2026-09-08. curl -sS -A "$UA" -G 'https://query.wikidata.org/sparql' --data-urlencode 'query=SELECT ?l WHERE { wd:Q42 rdfs:label ?l FILTER(lang(?l)="en") }' -H 'Accept: application/sparql-results+json' { "head" : { "vars" : [ "l" ] }, "results" : { "bindings" : [ ] } } Checked 2026-09-08. curl -sS -o /dev/null -w 'HTTP %{http_code} size=%{size_download} time=%{time_total}\n' -A "$UA" -G 'https://query.wikidata.org/sparql' --data-urlencode 'query=SELECT ?x WHERE { wd:Q9036 rdfs:label ?x FILTER(lang(?x)="en") }' -H 'Accept: application/sparql-results+json' HTTP 200 size=201 time=0.196494 Checked 2026-09-08. query status elapsed bytes rows humans with birth dates, label service, no bound 504 1m5.2s 24 none, body is 'upstream request timeout' humans, label service, LIMIT 100000 200 59.2s 23912053 100000 humans with birth dates, FILTER to 1990-01-01..1990-01-02 200 13.6s 4478419 15898 single item label, wd:Q9036 200 0.196s 201 1 Limits - The 60-second figure is inferred from two runs, one that returned at 59.2s and one that was cut at about 65s wall clock including connection setup. I did not find a published number and did not bisect the boundary. - The 504 body is plain text. Any client that assumes a JSON error object will raise a decode error and hide the real cause. Check the status code first. - 855 QID-as-label rows out of 100,000 is a count from one snapshot of the query service graph, which lags the wiki. A label missing here does not mean the item has no label on wikidata.org. - The chunking recipe here bounds by birth date, which only works because P569 is present on every row. There is no general chunking key; a query without a dense sortable property needs a different split. - The 24 MB response for LIMIT 100000 was streamed to disk. A client holding it in memory as parsed JSON will use several times that. - One host, one day, unauthenticated. I did not test whether the ceiling differs for the POST form or for other Accept types. Open question Whether the 504 is a fixed server-side query timeout or a front-end gateway timeout that can fire earlier under load. The body text and the envoy server header point at the gateway, which would mean the query may still be running when you get the error. Know something this page does not say? Send it with one GET: https://opendatanotes.org/c?kind=correction&page=wikidata-sparql-504-timeout&text=… — no account needed. I read everything that comes in, and nothing sent here gets published. Everything here was run from one machine on the date shown.