# uPlot: a deliberately small time series chart that hands the data work back to you

> A Canvas 2D charting library of roughly fifty kilobytes that plots time series and expects you to do parsing, aggregation and stacking decisions yourself.

**leeoniya/uPlot** — 📈 A small, fast chart for time series, lines, areas, ohlc & bars

- Repository: https://github.com/leeoniya/uPlot
- Stars: 10,509 · Forks: 463
- Language: JavaScript
- License: MIT
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/leeoniya-uplot

## Fifty kilobytes, and a claim you can check in the repo

The README opens with the size claim and backs it with a link into the repository rather than a marketing page, pointing at `dist/uPlot.iife.min.js`. Everything after that is built on the same idea: uPlot is a Canvas 2D renderer, not WebGL and not WebAssembly, and that choice is what keeps both the download and the startup cost low.

The headline numbers are specific. From a cold start, a chart containing 166,650 data points is created in 25ms, and after that the library scales at roughly 100,000 points per millisecond. For streaming, the README claims 3,600 points updated at 60fps costs about 10% CPU and 12.3MB of RAM, against 40% and 77MB for Chart.js and 70% and 85MB for ECharts.

What makes those numbers unusually credible is that the harness is in the repository. The tree has a `bench/` directory, the README links a raw data file called `results.json`, and each library in the comparison table has its own benchmark page you can open and rerun. The dates and hardware are listed too: an AMD Ryzen 7 PRO 5850U at 1.9GHz with 32GB of RAM, EndeavourOS with KDE, Chrome 113, a 4K display scaled to 1440p at a 1.5 device pixel ratio, run on 2023-03-11 against uPlot v1.6.24. That honesty is the point. It also means you can check the methodology rather than taking the claim on faith, and you can see that the same table shows Chart.js beating uPlot on time to first mousemove response while losing badly on the sustained numbers.

## A list of things this library will never do for you

Most chart libraries compete on features. uPlot has a section headed Non-Features, which reads more like a design contract, and it is the most useful thing in the README.

There is no data parsing, aggregation, summation or statistical processing. The instruction is to do it in advance, and the project links out to simple-statistics and to the author's own uDSV for that work. There are no transitions or animations, described flatly as pure distractions. There is no collision avoidance for axis tick labels, which means custom labels that are wider than the default can overlap unless you adjust spacing metrics yourself. There is no stacked series, and that refusal comes with an unusually strong argument: the README calls smooth spline interpolation with stacked data a case where your data is misrepresented, and links two articles about why stacked area graphs mislead. Smooth curves are still available; the project just tells you not to use them.

Built-in drag scrolling and panning are also absent, on the grounds that native zoom and selection behaviour is ambiguous. The suggested workaround is to add it yourself through the plugin and hooks API, with demo pages for wheel zoom and touch zoom as starting points. Read the whole list before you commit, because most of these are things you will not notice missing until you have built the panel.

## What the feature list does cover, and where the demos pick up the slack

The positives are a conventional time series feature set, done in a small API. Multiple series with per-series toggle, multiple y-axes with independent scales and grids, and an x-axis that can be temporal or plain numeric. Scales can be linear, uniform or logarithmic. Paths are pluggable, with linear, spline, stepped and bars renderers available, and line and area styles cover stroke, fill, width and dash.

Beyond that, the entries that go past the basics are worth picking out. Zoom with automatic rescale. A legend showing live values. Support for IANA time zone names and daylight saving transitions, which is harder than it sounds and quietly removes a whole category of bug. Explicit handling of missing data. Cursor synchronisation so several charts share a hover position. Data streaming for live updates. High and low bands, the standard candlestick or range visualization.

Documentation is the honest weak point. The README calls the docs a perpetual work in progress and says it seems that way. What it points to instead is three things: `docs/README.md` for a conceptual overview, `dist/uPlot.d.ts` where the full API is documented in the TypeScript declaration comments, and a runnable demo gallery that the README says covers the vast majority of the API. That last one is the real documentation. Each demo is a working page you can open, read and modify, which for a library this size is arguably more useful than prose would have been.

## Frameworks, Python, and how the package is built

uPlot is a plain JavaScript library, and wrappers around it are somebody else's job. The README lists React, Vue and Svelte wrappers maintained by Sergey Kalinichev, and a Python binding by Stephane Caron. If you are reaching for uPlot from a Python notebook, that second link is the entry point rather than the JavaScript package.

The package itself is an ES module with a CommonJS build alongside it and a TypeScript declaration file shipped in `dist`, which is the arrangement almost every library settled on after the module wars. Only `package.json`, the README, the license and `dist` are published, so the demos and benchmarks do not end up in your `node_modules`.

```json
  "scripts": {
    "build": "rollup -c --bundleConfigAsCjs",
    "demos": "node ./scripts/demos.mjs",
    "test": "node ./scripts/test.mjs",
    "test:server": "mocha test/server/*.mjs"
  },
```

The build is Rollup with the terser plugin for minification. Tests run through a script of their own with mocha for the server side, and there is an `UPDATE=1` environment variable that rewrites the expected output files, which tells you these are snapshot style tests with an explicit update path. Coverage is instrumented with istanbul and scoped to `src/**/*.js` and the built ESM bundle. Current package version is 1.6.32, with 1.6.31 and 1.6.30 preceding it.

## When a canvas chart is the wrong answer

The README is clear that Canvas 2D has a ceiling, and names the libraries to move to when you hit it. Past about 100,000 points in view, uPlot starts to struggle. The first thing it suggests is unclogging the rendering pipeline, which is a real technique and means you batch updates rather than redrawing on every event you happen to receive.

If that is not enough, the recommendation is a WebGL or WebGPU approach, with webgl-plot, TimeChart and implot named as candidates. That is worth taking at face value. uPlot's advantage over those options is startup cost and code size, and once the data volume is high enough that a GPU is justified anyway, that advantage has already been spent.

The 136 open issues on the repository are the other thing worth sizing up. For a library at this scale with a decade of users, that number is unremarkable, and a good share of it will be feature requests for things the Non-Features list rules out. Treat the issue tracker as a statement of where the design boundary is rather than as a backlog of bugs. The last push was 2026-09-20, well within recent history, so the code moves even though the scope does not.

## Conclusion

uPlot makes a clear bet: a time series chart should draw time series and nothing else, and the surrounding work belongs to the caller. The result is a library small enough to load without thinking about it and fast enough to stream at sixty frames a second on a page that already has other work to do. The bet also has a cost, and the project is unusually straight about it. There is no aggregation, no statistics, no stacked series, no animations, no drag panning and no tick collision avoidance, so a dashboard with more than a couple of panels per chart will need plugins you write yourself. Documentation is the other soft spot: the README describes the docs as a perpetual work in progress and points at a conceptual overview, a TypeScript declaration file and a demo gallery instead. Read that demo gallery, since it is closer to real documentation than the prose is. The published benchmarks are dated March 2023 and were taken on one specific laptop, so treat the comparative numbers as a reason to try it rather than as a promise about your hardware.

## FAQ

### What is uplot?

uPlot is a small, fast JavaScript charting library for time series, drawn with the Canvas 2D API rather than SVG or WebGL. It plots lines, areas, OHLC and bars, ships as roughly 50 KB minified, and leaves data parsing and aggregation to the caller.

### How does uPlot compare to Chart.js and ECharts?

The README's benchmark table puts uPlot at 47.9 KB against 254 KB for Chart.js v4.2.1 and 1000 KB for ECharts v5.4.1, with far lower CPU and memory during a 3,600 point stream at 60fps. Those numbers were recorded on 2023-03-11 on one Ryzen 7 machine, so they are worth reproducing rather than trusting outright.

### Does uPlot support stacked series or bar charts?

Bars are supported through a pluggable path renderer, but stacked series are an explicit non-feature. The project argues that stacking plus smooth interpolation misrepresents data and links two articles on the subject, while leaving spline interpolation available for cases where it is appropriate.

### What are the wrappers for using uPlot with React, Vue or Svelte?

The README links community wrappers by Sergey Kalinichev covering React, Vue and Svelte, plus a Python binding by Stephane Caron. The npm package itself is plain JavaScript with an ES module build, a CommonJS build and TypeScript declarations.

### Can uPlot handle more than 100,000 points at once?

The README says streaming stays at 60fps in most sane cases but may struggle beyond 100k in-view points. Its advice is to unclog the rendering pipeline first, then to reduce update frequency or move to a WebGL or WebGPU library.

## Sources

- [Issues](https://github.com/leeoniya/uPlot/issues)
- [leeoniya/uPlot on GitHub](https://github.com/leeoniya/uPlot)
- [License: MIT](https://github.com/leeoniya/uPlot/blob/master/LICENSE)
- [README](https://github.com/leeoniya/uPlot/blob/master/README.md)
- [Releases](https://github.com/leeoniya/uPlot/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/leeoniya-uplot
