Large files, privately
The reason to split a CSV is almost always that it's big, and big CSVs are almost always sensitive — customer exports, payroll runs, transaction logs, mailing lists. Uploading that to a web service means trusting an unknown server, an unknown retention policy, and an unknown breach history with exactly the data you'd least like to leak; the desktop alternatives want an install or a subscription for what is, at heart, a loop over lines. This page does the loop in your browser: the file API reads the file into the tab, the split happens in memory with a progress bar, and each part is a download generated on your machine. Nothing is transmitted, because there is nothing to transmit to.
Honest limits: the ceiling is your browser's memory, not a server plan. Files of a few hundred megabytes work on typical hardware; for gigabyte-class files, close other tabs first and expect the progress bar to earn its keep. If the browser can't hold the file, no client-side tool can help — that's the point where command-line tools on your own machine are the right answer, and we'd rather say so than pretend.
Split by rows per file
The classic mode: pick how many data rows each part should hold, and the file is dealt out in order — 10,000 rows at 3,000 per file gives you 3,000 + 3,000 + 3,000 + 1,000. The last part holds the remainder; row order is preserved; and the count refers to data rows, so the repeated header doesn't eat into your quota. This is the mode for import tools with row limits per batch and for handing a team chunks of a work queue.
Split into N equal files
Sometimes the constraint is the number of parts, not their size — five files for five teammates, twelve for twelve parallel workers. This mode divides the rows as evenly as arithmetic allows: 1,000 rows into 3 files is 334 + 333 + 333, never 500 + 500 + 0. If you ask for more files than there are rows, you get one row per file and no empty parts.
Split by max file size
Upload forms and email attachments cap bytes, not rows, so this mode targets a maximum size per part. It's honestly approximate: rows are dealt into the current part until adding the next one would cross the limit, then a new part starts — so parts land just under the cap, rounded to the nearest whole row. A single row larger than the cap (it happens, with quoted text blobs) becomes its own oversized part with a warning rather than being truncated, because a cut record is corrupt data.
Split by values in a column
The bonus mode: choose a column and get one file per distinct value — orders split by country, logs split by service, a roster split by department. Grouping is capped at 200 distinct values; beyond that you'll get a warning instead of a thousand-file download, because a column with that many values is usually the wrong grouping key (an ID column, most often) rather than a category.
Why the header rides along in every part
Row 1 of a CSV is the contract: it names the columns so that spreadsheets, import wizards, and dataframe libraries know what they're looking at. Split a file naively and only part 1 keeps that contract — parts 2 through N open as anonymous grids, and every import step downstream needs manual column mapping. This splitter writes the header as row 1 of every part by default. The toggle exists for the one real exception: recombining parts later by simple concatenation, where repeated headers would land in the data as bogus rows.
The quoted-newline trap (why line splitters corrupt CSVs)
CSV allows a quoted field to contain real line breaks — one record spanning several lines of the file. It's not exotic: any export with an address field, a comments column, or product descriptions has them. A splitter that counts newlines will sooner or later cut one of these records in half, leaving an unclosed quote at the end of one part and half a record at the start of the next — both files corrupt, often silently. This tool scans quote state as it walks the file, so a record boundary is only ever declared outside quotes; a multi-line record moves into a part whole or not at all. It's the single behavior that separates a CSV splitter from a line splitter, and it's tested here with exactly that vector.
Why CSVs get split at all
The classic trigger is the spreadsheet row ceiling: Excel worksheets hold at most 1,048,576 rows, so a bigger export simply won't open whole — rows past the limit are dropped on import, and the fix is to split the file below the ceiling first. The other regulars: import tools and APIs with per-request row or byte limits, email and upload size caps, and parallel processing where each worker takes a slice. In every one of those cases the requirement is the same — clean parts, each with the header, no record cut mid-way — which is the whole spec of this page.