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 (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 (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 (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 (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 (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 keyThat is a genuine absence, not a label-service bug: asking for the label directly returns no rows for the same item. Source (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.txtHTTP 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 -5HTTP/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.