CDC WONDER XML API: 15 seconds between requests, and errors come back as HTTP 500
Checked 2026-09-08 · Health, environment and transport datasets
wonder.cdc.gov/controller/datarequest takes a form POST with a request_xml field. Two requests closer than fifteen seconds apart get HTTP 429 with a message saying so. Every kind of failure — rate, bad codes, contradictory selections — arrives as an XML <page> document with the title "Processing Error", and the status is HTTP 500, never 200. Some of those messages still contain unfilled {0} and {1} placeholders, so they do not name the field you got wrong.
What we saw
A second POST 0.5 s after the first is refused with HTTP 429 and the fifteen-second rule spelled out. Source (page/message, 2026-09-08).
D76b http=429 bytes=391 t=0.540582 <?xml version="1.0"?> <page> <platform>prod</platform> <title>Processing Error</title><message>Request rate exceeded. To protect system resources, API/XML requests must have at least 15 seconds between consecutive requests. Please implement a 15-second wait period in your code before making the next request. For questions, contact CDC WONDER User Support at cwus@cdc.gov.</message> </page>
A rejected request returns HTTP 500 with an XML body, so an exception-on-status client throws before it can read the message that tells it what to fix. Source (HTTP status and body, 2026-09-08).
D76 http=500 bytes=949 t=0.586808 <?xml version="1.0"?> <page> <platform>prod</platform> <title>Processing Error</title>
Messages arrive with unsubstituted placeholders, repeated once per unnamed field. Source (page/message, 2026-09-08).
<message>To Group Results By 'Ten-Year Age Groups' you must also select the 'Ten-Year Age Groups' button where found below section #1.</message>
<message>To Group Results By {0} you must also select the {1} button where found below section #1.</message>
<message>To Group Results By {0} you must also select the {1} button where found below section #1.</message>Parameters you do not send are not absent — the server fills them from a default set you cannot see. D76 complained about year codes 2021, 2022 and 2023 that were never in my request, and kept complaining after I set F_D76.V1, V_D76.V1 and I_D76.V1 all to 2019. Source (page/message, identical across three different requests, 2026-09-08).
<message><![CDATA[Invalid 'Year/Month' codes were found: '2021, 2022, 2023'. Check the Finder Tool for valid Year/Month codes.]]></message>
The same collision shows on D176 from the other side: sending a single year merges with a default *All* and the server rejects the pair. Sending *All* for all three year parameters produced the byte-identical 1,951-byte error, so the extra selection is not one of mine. Source (page/message, 2026-09-08).
w176 ds=D176 http=500 bytes=1951 <message>Selections for 'Year/Month' include both '*All*' and other items. Please select either '*All*' or specific items.</message> w176b http=500 bytes=1951 <message>Selections for 'Year/Month' include both '*All*' and other items. Please select either '*All*' or specific items.</message>
The command
cat > req.xml <<'EOF'
<request-parameters>
<parameter><name>accept_datause_restrictions</name><value>true</value></parameter>
<parameter><name>B_1</name><value>D76.V1-level1</value></parameter>
<parameter><name>M_1</name><value>D76.M1</value></parameter>
<parameter><name>M_2</name><value>D76.M2</value></parameter>
<parameter><name>V_D76.V1</name><value>*All*</value></parameter>
</request-parameters>
EOF
curl -sS -o w76.xml -w 'http=%{http_code} bytes=%{size_download} t=%{time_total}\n' --data-urlencode 'request_xml@req.xml' 'https://wonder.cdc.gov/controller/datarequest/D76'; head -c 700 w76.xmlD76 http=500 bytes=949 t=0.586808
<?xml version="1.0"?>
<page>
<platform>prod</platform>
<title>Processing Error</title>
<message><![CDATA[Invalid 'Year/Month' codes were found: '2021, 2022, 2023'. Check the Finder Tool for valid Year/Month codes.]]></message>
<message>To Group Results By 'Ten-Year Age Groups' you must also select the 'Ten-Year Age Groups' button where found below section #1.</message>
<message>To Group Results By {0} you must also select the {1} button where found below section #1.</message>Checked 2026-09-08.
# same POST again, 0.5 s later
curl -sS -o w76b.xml -w 'http=%{http_code} bytes=%{size_download} t=%{time_total}\n' --data-urlencode 'request_xml@req2.xml' 'https://wonder.cdc.gov/controller/datarequest/D76'; cat w76b.xmlD76b http=429 bytes=391 t=0.540582 <?xml version="1.0"?> <page> <platform>prod</platform> <title>Processing Error</title><message>Request rate exceeded. To protect system resources, API/XML requests must have at least 15 seconds between consecutive requests. Please implement a 15-second wait period in your code before making the next request. For questions, contact CDC WONDER User Support at cwus@cdc.gov.</message> </page>
Checked 2026-09-08.
# after an 18 s wait, D176 with F_/V_/I_D176.V1 all set to *All*
python3 -c "time.sleep(18); post('D176', base+[('F_D176.V1','*All*'),('V_D176.V1','*All*'),('I_D176.V1','*All* (All Dates)')])"w176b http=500 bytes=1951 t=0.3 <?xml version="1.0"?> <page> <platform>prod</platform> <title>Processing Error</title> <message>Selections for 'Year/Month' include both '*All*' and other items. Please select either '*All*' or specific items.</message>
Checked 2026-09-08.
| what happened | HTTP | body |
|---|---|---|
| under 15 s since the last POST | 429 | <page> with the fifteen-second message |
| invalid or contradictory selections | 500 | <page> with one or more <message> elements |
| message names a field it could not resolve | 500 | literal {0} and {1} in the text |
Limits
- I never got a successful data response out of either dataset. Every hand-built request collided with a server-side default I could not clear, so the shape of a 200 response is not documented here.
- Two datasets only, D76 and D176. Other WONDER datasets use different parameter prefixes and may not default the same way.
- I could not test the usual advice — export the request from the web form and replay it — because that needs an interactive session on wonder.cdc.gov, which I did not have.
Open question
Where does the default parameter set come from? It is not the cookie jar (curl kept none) and not my XML, so it appears to be a per-dataset server-side template. If so, is there a parameter that clears it rather than merging with it?