QuickChart API for Server-Rendered Charts and QR Codes
Chart image and QR code web API
At a glance
- What is it?
- QuickChart turns Chart.js configurations and QR code parameters into PNG or SVG images through an Express web API. It fits static email, chat, and reporting workflows, but its support for arbitrary JavaScript requires careful sandboxing when self-hosted.
- Who is it for?
- Adopt QuickChart when a static chart or QR image must be generated from a URL and the team can operate an Express service. Do not choose it when you need client-side chart interaction or cannot sandbox configuration-derived JavaScript.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why QuickChart Uses URL-Generated Images
QuickChart addresses a specific delivery problem: Chart.js normally renders inside a browser, but email, SMS, chat messages, and many document workflows cannot execute the JavaScript needed by an interactive chart. The service accepts a chart definition in a URL and returns an ordinary image that can be embedded in those static environments. Its QR endpoint applies the same pattern, producing a code from text supplied as a query parameter.
The intended users are developers building static reports, notifications, dashboards, or server-side images without maintaining a browser rendering environment. QuickChart supports Chart.js v2 through the main dependency and Chart.js v3 and v4 through the `version` parameter. It also includes plugins for annotations, data labels, pie-chart outlabels, radial gauges, box-and-violin plots, doughnut labels, and color schemes. This makes the project more than a generic image endpoint, although the README warns that custom plugins are not available for Chart.js versions at or above 3.0.0.
The service is not limited to chart images. The `/qr` route generates PNG by default or SVG on request, and its parameters cover image size, quiet-zone margin, error correction, and the two foreground and background colors. The main design benefit is URL-addressability. A chart or QR code can become a link rather than application state that every recipient's software must interpret.
QuickChart's Chart.js Rendering Pipeline
A typical `/chart` request carries image dimensions and a `c` parameter containing a Chart.js-style object. The object declares a chart `type`, then supplies `labels` and one or more `datasets`. In the README example, the datasets are named `Dogs` and `Cats`, with each category carrying its own numeric value. The server returns the resulting bar chart as an image.
The package dependencies show how this rendering path is implemented. QuickChart includes `chart.js-node-canvas`, `canvas`, `sharp`, `text2png`, `pdfkit`, and image processing dependencies. It also includes separate Chart.js packages named `chart.js-v3` and `chart.js-v4`, each pinned to a specific release through an npm alias. The repository contains the rendering implementation under `lib/`, while `index.js` is the package entry point and server entry point.
The QR route is separate. It uses the `qrcode` package and accepts `text`, which is required, plus `format`, `size`, `margin`, `ecLevel`, `dark`, and `light`. PNG is the default format, the default side length is 150 pixels, the default margin is 4 modules, and the default error correction level is M. The documented dark and light defaults are `000000` and `ffffff`.
One version constraint deserves attention: each QuickChart instance should use one Chart.js version, and switching between versions in the same instance is described as not well supported. Teams should therefore settle on a version before integrating a substantial collection of chart templates.
Installing QuickChart and Running a First Image
For a quick first use, Docker avoids separate handling of Cairo, Pango, libjpeg, libgif, fonts, and other native dependencies. The repository's `Dockerfile` builds from `node:18-alpine3.17`, installs the rendering libraries and fonts, exposes port 3400, and starts `index.js`. Build the image from the repository directory with the documented command:
docker build -t ianw/quickchart .After the build completes, the following command starts the server and maps its port 3400 to port 8080 on the host:
docker run -p 8080:3400 ianw/quickchartThe resulting local service uses the same web endpoints described for the hosted QuickChart service. A browser can then request the chart or QR routes under `http://localhost:8080`. The README does not document a health-check path, so container startup should be checked by requesting one of those documented endpoints.
For a local installation, the README says chart generation requires Cairo, Pango, libjpeg, and libgif. On Linux, its fresh-install script also installs yarn, node, and monit:
./scripts/setup.shAfter the system dependencies are available, install JavaScript dependencies with either supported package manager:
yarn installThe repository also permits npm:
npm installStart the installed server directly on port 3400 with:
node index.jsThe `PORT` environment variable changes that port. The `package.json` also defines `npm start` as `node --max-http-header-size=65536 index.js`, which starts the same entry point with an explicitly increased HTTP header limit.
The `/chart` Configuration Boundary
The strength of `/chart` is also its main adoption constraint. Chart configurations may contain arbitrary JavaScript, as the README states directly. That makes the renderer a code-execution boundary when users or upstream systems can influence the configuration. A public self-hosted endpoint should not simply forward untrusted input to Chart.js.
The documentation recommends proper sandboxing and warns self-hosters not to expose the service carelessly. The repository includes `express-rate-limit`, but the README does not describe a complete hardening recipe for hostile configurations. It also points to NGINX configuration under `nginx/` for a production-style deployment and mentions an external `nginx-proxy` image. Those components address proxy deployment, not by themselves the entire JavaScript sandbox requirement.
There is another compatibility boundary. A URL that renders correctly under Chart.js v2 may use a plugin or behavior that does not carry over to v3 or v4. The `version` parameter lets callers select among supported Chart.js lines, but each instance is expected to remain with one version. The dependency declarations pin v3 to 3.9.1 and v4 to 4.0.1, while the ordinary `chart.js` dependency is on the 2.9.4 line. This version split should be treated as part of the API contract rather than an incidental package detail.
The package metadata reports version 1.8.1, while the listed release history ends with v1.8.0 from 2022-12-28. The repository is not archived, and its last push was on 2026-10-12, but the README's main `start` command does not discuss a migration procedure for the package version.
QuickChart Compared With Browser Rendering and Direct Libraries
The clearest alternative is direct browser-side Chart.js rendering. A web application can include Chart.js, create a canvas, and let the user's browser render an interactive chart without sending the configuration to a separate image service. That avoids the QuickChart server and its native rendering stack. It is the wrong alternative when the destination is static, however. Email, SMS, or chat content generally needs a finished image rather than a JavaScript bundle.
A second alternative is calling a client library from QuickChart's ecosystem, such as `quickchart-js`, `quickchart-python`, `quickchart-ruby`, `quickchart-php`, `quickchart-csharp`, or `quickchart-java`. Those libraries wrap request construction for the service. They do not replace the renderer, so the operational and sandboxing considerations of a self-hosted QuickChart server remain relevant.
For QR generation, an application can use the `qrcode` dependency itself in its own server process instead of exposing QuickChart's `/qr` endpoint. The practical difference is the interface: QuickChart centralizes chart and QR rendering behind two HTTP routes, while a direct library integrates rendering into application code. HTTP is convenient for precomposed links and distributed clients. Direct integration gives the application tighter control over its process boundary, but requires assembling and maintaining that rendering path separately.
AGPL-3.0 and Operational Upgrade Cost
QuickChart is distributed under AGPL-3.0 according to both the repository metadata and the license identifier in `package.json`. Any organization modifying or offering the service over a network must review its own AGPL obligations. This article does not provide legal advice. The license is especially relevant to a hosted or self-hosted deployment because the project is designed to run as a network service.
The operational cost is more concrete. A source installation needs native rendering libraries and fonts, while Docker packages many of them into an image based on Node 18 and Alpine 3.17. The Docker build removes build dependencies after installation, but it still has to compile or install native packages during the build. Operators must also decide whether to place NGINX in front of Node, as the production service does, and how to isolate rendering of untrusted configurations.
Upgrading follows the repository's package and lockfiles, but the README does not describe version migrations, rollback, configuration compatibility across releases, or a formal support window. The repository's `format`, `test`, and `test:watch` scripts provide development commands, yet they are not an operator upgrade procedure. Teams adopting this service should base their planning on the explicit runtime, Chart.js, plugin, and license compatibility they actually need rather than assuming that every chart URL will move cleanly between versions.
Editorial conclusion
Adopt QuickChart when a static chart or QR image must be generated from a URL and the team can operate an Express service. Do not choose it when you need client-side chart interaction or cannot sandbox configuration-derived JavaScript. Before deployment, verify the selected Chart.js version, plugin availability, security boundary, and AGPL-3.0 obligations, starting with the exact `/chart` configuration exposed by your service.
Frequently asked questions
How do I self-host QuickChart with Docker?
Build the repository image with `docker build -t ianw/quickchart .`, then run `docker run -p 8080:3400 ianw/quickchart`. The container exposes the server on port 3400.
Which Chart.js versions does QuickChart support?
The README says QuickChart supports Chart.js v3 and v4 through the `version` parameter, and package.json also includes the Chart.js 2.9.4 line. Custom plugins are currently unavailable for versions at or above 3.0.0.
Can I expose a self-hosted QuickChart server to untrusted users?
The README warns against exposing the service carelessly because Chart.js configurations may contain arbitrary JavaScript and must be sandboxed.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/typpo-quickchart)Was this useful?