Issue Nº 14 — Aug 31, 2026
QuickChart turns a broken chart config into a blank image, not an error
Issue fourteen covers QuickChart, an API that renders a Chart.js config into an image instead of returning JSON. This session generated charts, a QR code, and an SVG, all with no key and wide-open CORS. It also found a gap: a config that fails to parse gets a plain-text error in a response header. A config that parses fine but names an unsupported chart type returns 200 and a blank picture instead, with no error signal anywhere in the response.
What it covers
QuickChart takes a Chart.js configuration and renders it as an image. A caller passes the config in the c parameter of a GET request, or posts it as JSON to the same path, and gets back a picture, not JSON. A live GET this session to /chart, with a three-bar Chart.js config, returned 200 and a 14,355-byte PNG. The same call with format=svg on the query string returned 200 and a 26,920-byte SVG instead, matching the formats field already on file.
A second hero endpoint, /qr, turned the text greatapis.com into a 909-byte PNG QR code from a plain GET with one parameter. Neither endpoint needed a key.
The version parameter picks which Chart.js release renders the chart. That same bar-chart config, sent with version=4, returned a 14,411-byte PNG instead of the 14,355 bytes above. Sent with version=2, it returned 14,355 bytes: byte for byte the size of the call that named no version at all. Version 2 is the default, and QuickChart runs more than one Chart.js release on its own servers.
No key, and CORS answers every check
No key or sign-up was needed for any call this session. This matches the auth: None already on file. An OPTIONS preflight against /chart, sent with an Origin header of https://greatapis.com, returned 200. The response carried access-control-allow-origin: *, access-control-allow-methods: GET, POST, and an allow header listing GET,HEAD,POST. This confirms the cors: yes on file.
The two endpoints do not answer alike on cookies. A plain GET to /chart sets a GAESA cookie, an App Engine session-affinity cookie, and so does the preflight above. Four GETs to /qr this session, each with different text and no cookie sent, set no cookie at all. Every one of the four was a cf-cache-status: MISS, so each reached the origin rather than a Cloudflare cache. The two paths run on different backends. That cookie plays no part in the CORS behaviour above.
A broken config renders a blank picture, not an error
A config string that fails to parse gets a real error. Sending c={type:"bar" with the closing brace left off returned 400. The response header read x-quickchart-error: Chart error: Error: Unexpected token ';' - 1:12. QuickChart names the exact parse failure in a header, not just the status line.
A config that parses as valid JSON but names a chart type QuickChart doesn't support behaves differently. Sending c={"type":"nope"} returned 200, not 400. The response is a real PNG, 2,424 bytes. Decoding it gives a 1000x600 RGBA canvas, and all 600,000 of its pixels hold the same value: zero red, zero green, zero blue, zero alpha. The image is fully transparent, with no opaque pixel anywhere. QuickChart sized and encoded a chart surface, then drew nothing on it. Composite that PNG onto a dark page and it leaves no mark.
That 200 response carries no x-quickchart-error header at all, even though every response lists that header as available in access-control-expose-headers. A caller that checks only the status code, or only the error header, sees success. Only opening the image shows that nothing rendered.
No rate-limit header shows up on any call
The entry's rateLimit field cites a cap of 60 charts a minute and 1,000 a month on the free tier. That figure comes from QuickChart's FAQ, which also gives the burst rate as 1 chart a second. The pricing page says only that a rate limit applies. Five rapid GET calls to /qr this session, sent back to back, all returned 200. None carried a rate-limit, retry-after, or quota header.
This does not prove there is no cap. It only shows that QuickChart, like Fiscal Data in issue thirteen, does not surface one in its response headers. A caller has no way to see, from the response alone, how close a burst of calls comes to the free tier's monthly ceiling.
QuickChart, by the numbers
60 charts/min & 1,000 charts/month on the free tier; the $40/month Professional plan lifts both limits
- GET/chart
- GET/qr