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

CSVJSONNDJSONParquet
Human-readableYesYesYesNo (binary)
TypesNone — everything is textStrings, numbers, booleans, nullSame as JSONRich: int64, date, decimal, …
Nested dataNoYesYesYes
StreamingLine by lineNeeds a streaming parserLine by lineBy row group
CompressionExternal (gzip)ExternalExternalBuilt in, per column
Best forSpreadsheets, simple exportsAPIs, config, documentsLogs, bulk loadsAnalytics, 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:

Python
import pandas as pd

df = pd.read_parquet("sample-100k-rows.parquet")
print(df.dtypes)

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.

Sample files for this guide