CSV to Chart
Drop a CSV and a chart appears. Not a blank canvas with a Create button on it, and not a count of rows by the first column it found: the page reads what each column means and draws the chart that file is actually about. Switch shape, swap columns, change the aggregate, then take the PNG, the SVG or the numbers behind it. Everything happens in your browser.
Nothing to hand? Try with sample sales data · six months of orders, charted the moment it loads.
Need to filter or join before charting? Open the app
The first chart should already be the right one
Most online chart makers open with an empty grid and ask you to nominate an x axis. That is a reasonable interface for someone who already knows what they want to see, and a terrible one for the far more common case: you have a file, you have not looked at it yet, and you want to know what is in it. So this page inverts the order. It reads the file first, decides what the file is about, and draws that. The controls are there to disagree with it.
Deciding what a file is about starts with reading every column once and giving it a role, which is a stronger statement than a type. revenue is not merely numeric, it is money, so it renders as $16.2k on the axis, in the bar labels, in the tooltip and in the exported CSV header, all from one inference. signup_date is not merely text, it is a date, so it becomes a time axis with a sensible bucket size. order_id looks numeric and is an identifier, so it is never offered as something to sum. Roles are read from the values first and the header name second, which matters: a column called amount holding the words pending and settled is a status, and a column called x1 holding $4.20 is money.
From there the choice is four lines long and entirely predictable. A measure and a date give you that measure over time. A measure and a category give you that measure by category. A measure with nothing to group by gives you its distribution. Categories with no measure at all give you counts. The aggregate starts at Sum whenever there is a real measure to sum, because defaulting to a count of rows produces a chart that is technically correct and answers a question nobody asked.
Seven shapes and six controls
Everything on the panel redraws from rows that are already parsed, so switching shape is instant and the file is never read twice.
- Chart. Bar puts the categories down the left and the value to the right of each bar, which is the shape you can read without a mouse. Column stands them up for short labels or a time sequence. Line and Area are for movement over time, Area adding a low-opacity fill under the stroke. Donut is for parts of a whole, with the percentage in the legend. Scatter plots two measures against each other and reports the correlation. Histogram bins one measure. Boxplot shows the spread, with the whiskers at 1.5 times the interquartile range and every point past them drawn as an outlier dot.
- Measure. The column being aggregated. Set it to Count rows and the chart counts records instead, which is the right answer for a file with no numbers in it.
- Dimension. The column being grouped by. Choose a date column and the chart becomes a time series; choose a category and it becomes a breakdown.
- Aggregate. Sum, average, count, count distinct, minimum, maximum and median. Median is the one most tools omit, and it is the one you want the moment a handful of enormous orders drags the mean somewhere no customer actually lives.
- Show and Sort. Top 5, 10, 20, 50 or everything, ordered by value in either direction, by label alphabetically, or left in file order. File order is what a funnel or a set of pipeline stages needs, where the sequence is the meaning.
- Time grain. Auto, day, week, month, quarter or year. Auto reads the span of the column: about six weeks of data buckets by day, seven months by week, three years by month, longer by quarter and then year.
Worked example: six months of orders
Five columns, a date, two categories and two numbers. The first few rows:
date,region,product,units,revenue
2024-01-02,West,Doohickey,58,$12,275.12
2024-01-04,West,Sprocket,13,$529.49
2024-01-06,North,Widget,41,$3,908.60
2024-01-08,East,Gizmo,7,$1,204.15
Dropped on this page, nothing is clicked and this is what appears: a line chart titled revenue over time, with a caption reading Sum of revenue · monthly totals · 6 bars, a kicker reading TREND in the top right, and a y axis marked $0, $40k, $80k rather than 0, 40000, 80000.
Three decisions are visible in that one sentence. revenue won over units as the measure because money outranks a count when both are present. The grain is monthly because six months of near-daily rows is about 170 points, and 170 ticks is a smear. And the caption states the bucketing out loud, which is not decoration: a competitor's dashboard labels the same shape weekly totals · 279 weeks on a file spanning one year, because it buckets by distinct date and calls the result weeks. A caption that states the grain cannot lie about it quietly.
Now switch Chart to Bar and Dimension to product. The title becomes revenue by product, the kicker becomes BREAKDOWN, and five horizontal bars appear with the product name in grey on the left and the value in mono to the right of each bar: $182.4k, $166.9k, and so on. There is no value axis at all, because with the numbers written on the bars an axis is redundant furniture.
Switch Aggregate to Median and the same five bars redraw as the median order value per product, which is a different and often more useful story. Switch to Scatter, set Measure to units and Y measure to revenue, and the caption gains r = 0.62 · moderate positive with a note underneath reminding you that correlation is not causation. Then Download chart data gives you a two-column CSV holding exactly the numbers on screen, so the chart in your deck and the table in your appendix cannot disagree.
Why these charts look the way they do
None of the styling here is a theme someone picked. Each rule exists because the alternative made a chart harder to read.
- One colour unless the encoding needs more. A bar chart of revenue by product is one measure split by one dimension. Giving each bar its own hue implies the colours mean something, and they do not. Categorical colour is spent where it does work: donut slices, treemap tiles, timeline lanes, scatter groups. The palette behind it is machine-validated, with every adjacent pair clearing a colour-vision-deficiency separation floor in both light and dark mode.
- Colour means one thing at a time. Green is positive movement, rust is decline, amber flags an outlier. A waterfall's bars are green and rust for that reason and no other, so a hue never carries two meanings on one page.
- Dotted horizontal gridlines, and nothing else. No vertical grid, no axis line, no tick marks. Gridlines exist to let you compare heights; every other rule on the canvas is ink competing with the data.
- Three labels on a long axis. First, middle, last. Twenty-four tick labels rotated at forty-five degrees is a decoration that reads as work.
- Metadata in mono, prose in sans. Axis ticks, the kicker, the caption and the value labels are all monospaced. It puts a visible line between what the chart says and what the page says about the chart, and it makes digits line up.
- Values written on the bars. Reading a chart should not require a mouse, a screenshot in a document has no hover state, and a printed page has no tooltips at all.
- Bars capped at 48 pixels. Four categories across a wide panel used to produce four hairlines with acres of white between them.
- Dark mode swaps tokens, not filters. Every colour is defined twice and the chart is rebuilt from whichever set is live, so nothing is a washed-out version of the light theme.
Four exports, and what each one is for
- Download PNG. Two-times pixel density, on the panel's own background rather than a transparent one, so it does not turn into a black rectangle when it lands on a dark slide.
- Copy image. The same PNG straight onto the clipboard. Paste it into a doc, a ticket or a chat message without a file ever touching your disk.
- Download SVG. The chart is rendered a second time through a vector renderer and serialised. Real paths and real text, sharp at any size, editable in Illustrator, Figma or Inkscape when the colours have to match a house style.
- Download chart data. The aggregated numbers as CSV: one row per bar, point or slice. This is the export that stops a deck and its appendix disagreeing, and it is also the fastest way to check the arithmetic yourself.
The preview table under the chart holds the same numbers, and Copy to clipboard puts them on the clipboard as CSV. To publish a chart on a page rather than in a document, build an embed: the data and the configuration are compressed into the URL of an iframe, so the chart renders from the link with no server and nothing stored.
What this page will not do
Being straight about the edges, because these are the ones people hit:
- One chart at a time. This page is a chart, not a dashboard. For a KPI strip, insights and a grid of panels from one file, use the dashboard builder.
- One series per chart. There is no multi-series bar or stacked area here. Two measures at once is a scatter; three is a job for the app's chart builder, which has per-series aggregation, percent stacking, log scales and reference lines.
- No filtering. The chart draws every row in the file. Filter first in the app, or split the file with the CSV splitter.
- No custom colours, yet. Palette choice lives on the embed builder, where a chart has to sit inside somebody else's page. Here the validated default applies.
- A header row is required. A file whose first line is data gets charted with values as column names. Add a header, or open the file in the app and promote a row.
- No forecast line. A dashed continuation drawn from six months of noisy data looks authoritative and is not. If a projection matters, do it deliberately somewhere it can be argued with.
Comma, semicolon, tab and pipe delimited files are all read without configuration, so a copy of cells straight out of a spreadsheet works in the paste box. Excel workbooks go to excel-to-chart and JSON to json-to-chart, both of which flatten to the same rectangle and then behave exactly like this page.
Frequently Asked Questions
Why does a chart appear before I choose anything?
Because the file already says what it is about. Every column is read once and given a role: a column of ISO dates is a date, a column of values with currency symbols is money, a column of short repeating words is a category. From there the choice is a four-line cascade. A measure plus a date gives a line of that measure over time. A measure plus a category gives a bar of that measure by category. A measure on its own gives a distribution. Categories on their own give counts. The aggregate defaults to Sum on a real measure, never to a count of rows, because a count of rows is almost never the number anyone came for.
Which chart types can I switch to?
Bar, column, line, area, donut, scatter, histogram and boxplot, from the Chart dropdown in the result panel. Switching redraws from the same parsed rows, so it is instant and it never re-reads the file. The specialist shapes live on their own pages, since each needs controls this one does not show: heatmap, pivot, treemap, sankey, timeline, map, waterfall and funnel.
Does my file get uploaded anywhere?
No. The parsing, the aggregation and the drawing all happen in your browser tab. There is no upload endpoint behind this page, no request carrying your rows, and nothing written to a server. Close the tab and the data is gone. That is also why the page keeps working with the network disconnected once it has loaded.
What is the biggest file it will chart?
The in-page limit is 100 MB, and in practice a few hundred thousand rows chart comfortably on a laptop. A chart is an aggregate, so the row count matters far less than the number of distinct categories: a million rows grouped into six regions is six bars and draws instantly. If you need to filter, join or clean before charting, the full editor streams files this size without loading them all at once.
Why did my category chart fold everything into an Other bar?
Because the column had more distinct values than the Show setting allows, and 900 hairline bars is a scroll bar rather than a chart. The values past the top N are added into one Other bar so the total still adds up, and the panel says how many were folded. Raise Show to 20, 50 or Everything if you genuinely want them all. Folding only happens for sums and counts: averaging a tail of averages would be arithmetic nonsense, so those charts simply stop at the top N.
Can I export the chart as an image?
Yes, four ways. Download PNG writes a 2x raster suitable for a slide deck. Copy image puts the same PNG on your clipboard, so it can go straight into a document without touching the filesystem. Download SVG renders the chart again through a vector renderer and saves real paths, which stay sharp at any size and can be edited in Illustrator or Figma. Download chart data saves the exact aggregated numbers behind the picture as CSV.
Why are the dates on my time axis grouped into months?
Because the grain is chosen from the span of the column, and a year of daily rows is 365 unreadable ticks. Up to about six weeks the chart uses days, up to seven months weeks, up to three years months, then quarters and years. Whatever it picked is stated in the caption under the title, so the axis never claims a bucketing it did not use. Override it with the Time grain dropdown.
What happens to values that are not numbers?
They are left out of the total and counted in a note under the chart. A cell holding N/A, a dash or an empty string is not zero, and quietly treating it as zero would drag every average down without saying so. Currency symbols, thousands separators, trailing percent signs and accounting parentheses are all read as numbers, so $1,234.50 and (250) both work.
Related
Chart your file
Drop the CSV, look at what it says, then take the PNG. No sign-up, no upload, no row cap.
Back to the chart maker