Guide
CSV vs JSON vs Parquet: choosing a data format
When plain text is enough and when a columnar binary format pays off — size, speed, types and tooling compared, with the same dataset in each format.
Every sample below holds the same fake customer records, so you can compare formats directly. The short answer: CSV for spreadsheets and simple exchange, JSON for APIs and nested data, NDJSON for streams and logs, and Parquet for analytics on anything large.
At a glance
| CSV | JSON | NDJSON | Parquet | |
|---|---|---|---|---|
| Human-readable | Yes | Yes | Yes | No (binary) |
| Types | None — everything is text | Strings, numbers, booleans, null | Same as JSON | Rich: int64, date, decimal, … |
| Nested data | No | Yes | Yes | Yes |
| Streaming | Line by line | Needs a streaming parser | Line by line | By row group |
| Compression | External (gzip) | External | External | Built in, per column |
| Best for | Spreadsheets, simple exports | APIs, config, documents | Logs, bulk loads | Analytics, data lakes |
Size
The same 100,000 records take about 15 MB as CSV, about 36 MB as pretty-printed JSON (every record repeats every key), about 30 MB as NDJSON, and about 4 MB as Snappy-compressed Parquet. Parquet wins because it stores each column together, and similar values compress very well.
Types and correctness
CSV has no types. The importer has to guess that 2024-03-01 is a date, that 0012345 should keep its leading zeros, and that 1e5 is not a number. Our tricky quoted fields sample shows how often those guesses go wrong. JSON adds numbers, booleans and null, but has no date type and loses precision above 2⁵³ — see JSON with every data type. Parquet stores an explicit schema, so a date is a date.
Speed
Parquet readers can skip columns and row groups they don’t need, so a query touching two columns of a wide table reads a fraction of the file. CSV and JSON must be parsed in full. For data under a few megabytes the difference rarely matters; for gigabytes it is dramatic.
Tooling
Everything opens CSV. JSON is native to JavaScript and every web API. Parquet needs a library — pandas, Polars, DuckDB, Spark, Arrow — but those read it in one line:
import pandas as pd
df = pd.read_parquet("sample-100k-rows.parquet")
print(df.dtypes)Related formats
Avro is row-based binary with an embedded schema (common with Kafka). ORC is Parquet’s columnar cousin from the Hive ecosystem. Arrow and Feather are for fast in-memory exchange between processes. The data pipelines use case has them side by side.