Split a CSV file

How to split a large CSV file into smaller files

rows.page splits a CSV of up to 1.5 GB in your browser: export chunks of up to 1,000,000 rows with SQL, or filter by a column value and export every matching row. It's free with no signup, and the file stays on your computer.

.csv.tsv
Drop a file here
Stays in your browserUp to 1.5 GB

No file handy? Open CO2 emissions by country and year (50k rows, 14 MB).

Why split a large CSV file

An Excel worksheet holds 1,048,576 rows. Open a bigger CSV and Excel loads only that many, warning "This data set is too large for the Excel grid. If you save this workbook, you'll lose data that wasn't loaded." Upload tools have caps too: ChatGPT takes CSV and spreadsheet files up to about 50 MB.

CSV splitting methods compared
MethodSplits byHeader in every fileLimit
rows.page SQL (LIMIT and OFFSET)Row countYesFiles up to 1.5 GB; 1,000,000 rows per query
rows.page filter (country:NL)Column valueYesFiles up to 1.5 GB; every matching row
GNU split -lLine countFirst file onlyRuns on disk
head, tail and split loopLine countYesRuns on disk
DuckDB PARTITION_BYEvery value of a column at onceYesRuns on disk

Split a CSV by row count in rows.page

Each chunk is one SQL query. Ordering by the hidden __rid column, the row number from the file, keeps the original order:

sql
SELECT * FROM data ORDER BY __rid LIMIT 500000 OFFSET 0
  1. Open https://rows.page and drop your CSV or TSV file on the page.
  2. Type the query above in the search box and press Enter.
  3. Open the Export menu and choose CSV to download the first chunk.
  4. Raise the offset by 500,000 (OFFSET 500000, then OFFSET 1000000) and export again until a query returns fewer than 500,000 rows.

SQL results stop at 1,000,000 rows, so keep LIMIT at 1000000 or below. Every CSV export has the header row, commas and UTF-8 without a BOM, and the __rid column is left out. Text cells that start with =, +, - or @ get a leading apostrophe so spreadsheets don't run them as formulas.

Split a CSV by column value in rows.page

To pull out the rows for one country, status or customer, use a filter instead of SQL. A filtered view exports every matching row, even past 1,000,000, with only the columns you have visible.

  1. Drop your file on https://rows.page.
  2. Type a filter in the search box, such as country:NL, country:NL OR country:BE or country:NL price:>20, or click a top value or histogram bar in the Columns panel.
  3. Hide any columns you don't want in the output.
  4. Open the Export menu and choose CSV, Parquet, JSON or JSONL.

To hand the subset to someone, click Share. It uploads the whole file, and the link opens with your filter applied, so the other person can still clear it and see every row.

Split a CSV of any size on the command line

GNU split

For files over 1.5 GB, or to write every chunk in one go, use split. It treats the CSV as plain lines, so the header ends up in the first file only:

bash
split -l 500000 big.csv part_

That writes part_aa, part_ab and so on, 500,000 lines each. Because split counts line breaks, not CSV records, a quoted field with a line break inside it can be cut in half.

Keep the header in every part

Save the header, split the rest, then put the header back on each part with a .csv extension:

bash
head -n 1 big.csv > header.csv
tail -n +2 big.csv | split -l 500000 - part_
for f in part_*; do cat header.csv "$f" > "$f.csv" && rm "$f"; done

DuckDB: one file per value

To write a separate file for every value in a column, run PARTITION_BY in the DuckDB command-line tool. DuckDB parses the CSV properly, including line breaks inside quoted fields:

sql
COPY (SELECT * FROM 'big.csv') TO 'out' (FORMAT csv, HEADER, PARTITION_BY (country), WRITE_PARTITION_COLUMNS true);

You get one folder per value, such as out/country=NL/data_0.csv, each file with its own header. Without WRITE_PARTITION_COLUMNS true, DuckDB leaves the country column out of the files and keeps it only in the folder name.

rows.page limits and prices

WhatLimit or price
Open a file in your browserFiles up to 1.5 GB, $0, no account, nothing uploaded
Share a link without an account$0, files up to 100 MB, link deleted 7 days after creation
Free account$0, 10 datasets kept, last 3 versions
Pro$12/month, 100 datasets, files up to 500 MB, private links
Max$39/month, 1,000 datasets, files up to 2 GB, private links

Questions

How do I split a CSV that is too big for Excel?

Excel worksheets hold 1,048,576 rows. Open the CSV in rows.page, run SELECT * FROM data ORDER BY __rid LIMIT 500000 OFFSET 0, export it as CSV, and repeat with OFFSET 500000, OFFSET 1000000 and so on. Each file gets its own header row.

How do I keep the header row in every split file?

Every CSV export from rows.page includes the header row. On the command line, run head -n 1 big.csv > header.csv, then tail -n +2 big.csv | split -l 500000 - part_, then for f in part_*; do cat header.csv "$f" > "$f.csv" && rm "$f"; done.

Why did my SQL export stop at 1,000,000 rows?

SQL results in rows.page stop at 1,000,000 rows. Keep LIMIT at 1000000 or below when you split by row count, or use a filter such as country:NL, which exports every matching row.

Can rows.page split a 2 GB CSV file?

Not in full. rows.page holds 1.5 GB per browser tab, so a 2 GB CSV loads partially with the note "Loaded the first N rows: the file is X, more than the browser can hold." Split it with split -l or DuckDB PARTITION_BY, or convert it to Parquet with the DuckDB command line, since rows.page doesn't hold Parquet to the 1.5 GB check.

Does rows.page upload my CSV when I split it?

No. Opening, filtering, running SQL and exporting all happen in your browser with DuckDB-WASM. Nothing is uploaded unless you click Share or push the file with curl -T data.csv https://rows.page.