Convert CSV to Parquet

Converting CSV to Parquet turns a text table into a columnar file with a real schema, typed columns and per-column compression, which is why the result is normally a small fraction of the size of the CSV. DuckDB, pandas and Spark read it directly, and the conversion runs in your browser.

  • Where it runs In your browser. The file is never uploaded.
  • Lossless Nothing is discarded. The Parquet holds exactly what the CSV held.
  • File size limit Up to 100 MB per file, free, without an account.

Up to 100 files at once. Mixed formats are fine.

A CSV carries no schema; a Parquet file carries one in its footer

Everything a CSV knows about itself is a header row, and a header row is a list of names. It cannot say that `amount` is a decimal, that `is_active` is a boolean, or that `customer_id` should never be treated as arithmetic. Every tool that reads the file has to work it out again, and every tool works it out slightly differently, which is why the same extract loads three ways in three places.

A Parquet file ends with a footer holding the schema, the number of rows, and per-column metadata. A query engine reads the footer first, which is a few kilobytes at the end of the file, and can tell you the column names and types before touching any data. That is a structural property rather than a convenience: it is what makes the format safe to hand to somebody who was not there when it was written.

Dictionary pages, Snappy, and why the file collapses

Three things happen to each column on the way in and they compound. The values are written in their binary form rather than as decimal text, so a number that took eleven characters in the CSV takes four bytes. Each column is then compressed on its own with Snappy, which is the default codec here. And a column whose values repeat is dictionary-encoded: the distinct values are written once into a dictionary page, and the column itself becomes a list of small integer references into it.

The dictionary is applied per column and only where it pays. The writer samples the first thousand values and uses a dictionary when at most half of them are distinct, which catches the columns you would expect — country, status, product code, currency — and skips a column of unique free text where a dictionary would be larger than the data. That is why the saving on an operational extract is enormous and the saving on a table of distinct sentences is modest, and it is worth knowing which of those your file is before predicting the result.

Row groups and the statistics that let a query skip pages

The rows are written in groups rather than as one block, between one thousand and one hundred thousand rows each, with pages inside them capped at a megabyte. Each column chunk within a group carries statistics, and those statistics are what turn a scan into a skip.

The effect is the one people mean when they say Parquet is faster. A query filtering on a date range reads the footer, sees that a row group holds values entirely outside the range, and never reads that group at all. A query naming two columns out of forty reads two columns’ worth of bytes rather than every row. Neither of those is available on a CSV under any circumstances, because a CSV has to be read from the beginning to find out where anything is.

What your CSV columns end up typed as

The type is inferred from the values rather than declared, since the source has nothing to declare. Each column is read in full: all booleans becomes BOOLEAN, all whole numbers inside the 32-bit range becomes INT32, numbers that are not all integers or not all small enough become DOUBLE, and anything else becomes a string. Nulls do not participate, so a numeric column with gaps stays numeric.

One stray value makes the entire column text, and that is deliberate rather than a limitation. Taking the type from the first row would write a column that begins with numbers as an integer column and turn every later non-numeric value into a null, producing a file that loads without complaint and has quietly deleted rows. A string column is visible, castable in one expression, and never loses anything. If a column arrives as text and you expected numbers, querying the values that fail to cast will show you a handful of rows with a footnote, a total or the word "none" in them — each of which is a true fact about the extract.

What the CSV already destroyed before Parquet saw it

The conversion reads the CSV with type inference, so `007` is the number 7 by the time the writer is choosing a column type, and the resulting INT32 column is a faithful record of a value that was already wrong. Parquet gets the blame for this regularly and does not deserve it: the loss happens at the text-parsing step, which is the same step every other CSV reader performs.

The columns at risk are the ones where arithmetic would be meaningless — postcodes, part numbers, phone numbers, account references, anything zero-padded. If the extract is under your control, export those columns quoted or with a prefix and they arrive as strings intact. If it is not, check the column in the output before the file is written anywhere durable, because the whole point of moving to Parquet is that the file stops being re-derived.

What the size difference looks like in practice

On a table of fifty thousand rows and six columns — an identifier, a product code, a city, a quantity, a price and a flag — the Parquet output measured 301 KB. The same data written as tab-separated text was about 1.8 MB, and a CSV of it differs from that only by which byte separates the fields and by the quotes around values containing commas.

That is roughly a sixfold reduction, and it is a reasonable expectation for operational data with repeated codes and categories. A file dominated by unique free text will do considerably worse, because neither the dictionary nor the binary encoding has much to work with there. Both figures assume no compression on the CSV; a gzipped CSV closes part of the gap, at the cost of being unqueryable until it is decompressed in full.

Reading the converted extract in DuckDB, pandas or Spark

No setup is required. DuckDB reads the file directly in a FROM clause, pandas reads it in a single call, and Spark treats it as a native table format. The file begins and ends with the four bytes PAR1, which is how each of them recognises it before reading the footer.

The first thing to look at after loading is the inferred schema rather than the first ten rows. A column you expected to be numeric that arrived as text is telling you something true about the CSV, and it is much cheaper to learn it now than after the file has been joined to three others and copied into a warehouse. Casting on the way into a table is one expression per column; casting blindly is how the rows you were protected from losing get lost anyway.

The honest limit on a large CSV in a browser tab

The whole table is held in memory: the CSV is parsed into rows, the rows are transposed into columns, and the columns are written. Tens of megabytes converts without ceremony and hundreds is where a tab begins to strain, which is a real ceiling and not a plan tier — there is no upload and nothing to pay for.

For a genuinely large extract the right instrument is DuckDB, which will read the CSV from disk and write Parquet in one statement without ever holding the file. Saying that plainly is more useful than letting a two-gigabyte conversion fail two-thirds of the way through. This page is for the file that fits, which is most of them, and for the case where installing something is not an option.

Why converting locally matters for a raw extract

Both halves run on this page: the CSV parser and the Parquet writer are libraries loaded on demand, and no request carries the file anywhere. A CSV heading for a data platform is very often the least redacted artefact in the whole pipeline — the raw dump before the joins and the masking — and uploading it to a converter is precisely the step a data protection policy exists to prevent.

It also removes a tier from the conversation. There is no queue, no maximum row count and no account, so the only question is whether the file fits in memory, which you can answer by looking at it.

When the data should stay a CSV

Parquet is a poor destination for anything a person has to read. It is binary, it is not editable, and a colleague without the right tooling cannot open it at all — the registry records its support as patchy for exactly that reason. If the file is going to a human being rather than an engine, send the CSV or a spreadsheet.

It is also the wrong target for a load that happens once and is then thrown away: the writing cost buys nothing if the file is never queried again, and a bulk loader reading delimited text directly will be faster end to end. Choose Parquet when the same data will be scanned repeatedly, filtered, joined and kept — which is exactly when the typed columns and the skipped row groups start paying for themselves.

How to convert a CSV extract into a Parquet file

  1. Drop the CSV onto this page, or click to choose one.
  2. It is parsed, typed column by column and written as Parquet, in your browser.
  3. Open it in DuckDB or pandas and check the inferred schema before storing it.

CSV and Parquet: text with no schema against a typed column store

CSV compared with Parquet
CSVParquet
Full nameComma-Separated ValuesApache Parquet
File extension.csv.parquet
Media typetext/csvapplication/vnd.apache.parquet
CompressionLossless — nothing is discarded
First published19722013
Published byApache Software Foundation
SpecificationRFC 4180
LicensingOpen standardOpen standard
Standing todayCurrentCurrent
Opens in a browserNo browserNo browser
Considered insteadXLSX, JSONJSON

What survives

Nothing is discarded. CSV and Parquet both store their content losslessly, so the conversion is a change of packaging rather than a change of quality, and it can be repeated without accumulating damage.

Opening the result

pandas reads both CSV and Parquet, so there is a way to check the result against the original without a second tool.

What each format is for

CSV was published in 1972. The specification is RFC 4180, and it is worth reading if the file has to outlive the tool that wrote it.

Parquet comes from Apache Software Foundation and dates from 2013. pandas, Apache Spark and DuckDB all read it.

CSV was published in 1972 and Parquet in 2013. The older one is generally the safer file to hand to somebody; the newer one usually does the job in fewer bytes.

CSV to Parquet: size, types and large extracts

Are my CSV files uploaded anywhere?

No. This conversion runs entirely inside your browser, so the file never leaves your device. You can confirm it yourself: open the network tab of your browser's developer tools and convert something. You will see the page load, plus the analytics and advertising the site is paid for with — and nothing carrying your file. The engine behind this particular pair is parquet-wasm, a WebAssembly build of the Apache Arrow reader; your browser fetches it once and caches it.

Why is the Parquet file so much smaller than the CSV?

Three reasons compounding. Values are stored in their binary form rather than as text, each column is compressed separately with Snappy, and a column with few distinct values is stored once as a dictionary with small integer references. A column of country codes or statuses costs almost nothing after that.

Does the Parquet file carry the column types?

Yes, in a footer, which is the main structural difference from a CSV. A query engine can list the column names and types without reading a single row, and it does not have to guess at anything on load.

How are the types decided if the CSV has none?

By inspecting every value in each column. A column whose non-empty values are all booleans becomes BOOLEAN, all whole numbers within the 32-bit range becomes INT32, other numbers become DOUBLE, and anything else — including one stray text value — makes the whole column a string.

Are leading zeros preserved?

No. The CSV parser reads 007 as the number 7 before the Parquet writer sees it, so a zero-padded column arrives as integers. Quote or prefix those columns in the source if they are identifiers rather than quantities.

How large a CSV can this handle?

The file is read into rows and transposed into columns in memory, so tens of megabytes is routine and hundreds is where a browser tab starts to strain. For a multi-gigabyte extract, DuckDB reading the CSV directly and writing Parquet is the right tool and this page is not.

Is the CSV uploaded to convert it?

No. The parser and the Parquet writer are both loaded into this page and run there, so the file stays on your machine — which for a raw extract is frequently the deciding factor.

More about these formats