The 25 MB wall
Gmail caps attachments at 25 MB. Plenty of import wizards choke lower than that, some CRMs stop at 10 MB, and a few internal ticketing tools accept email attachments only under 5. Somewhere out there is a limit with your name on it, and the day you meet it you will be holding a 60 MB orders export that absolutely has to travel by email before noon.
Splitting a CSV sounds like the simplest possible job — cut it every N lines — until you do it with a text editor and discover that CSV rows are not lines. Quoted fields wrap around commas and newlines; a record can legally span three physical lines; and the cut you made at line 1500 just bisected a customer's shipping note. The corruption is worse than obvious: both halves still open in Excel, and the damage surfaces two weeks later as a mysterious row count mismatch.
This splitter does the operation the way the format actually demands: parse the CSV properly, count real records, cut only at record boundaries, and stamp the header row on top of every chunk so each piece stands alone. It runs entirely in your browser — no upload, which matters for exactly the files that hit size limits, because they are usually the sensitive ones — and hands you a zip of ready-to-import parts.
Below: the workflow, the arithmetic of a clean split, a fully worked 10,000-row example, the quoted-newline trap explained, and the rows-versus-size decision. Plus the honest alternatives, because sometimes a splitter is the wrong tool and a cloud link is the right one.
Splitting a file in five steps
The splitter is at the top of the page. The standard run:
Load the CSV
File picker for big exports, paste for small ones. Delimiter detection runs immediately — comma, semicolon or tab — and the preview confirms the parse looks right before anything is cut.
Choose the split mode
Rows per chunk (say, 1,500 rows each) or target file size (say, 8 MB each), or give a number of chunks and let the tool balance rows across them.
Review the plan
Before writing anything, the tool shows the split plan: how many chunks, how many rows in each, and the estimated size of each file. Uneven last chunks are expected and visible — no surprises after the fact.
Split and download
One click produces the chunks, header included in each, bundled into a zip generated locally. Individual chunk download is available when you want one specific piece.
Verify, then send
The plan summary includes a checksum of the reassembled row count: chunks hold N data rows plus one header each, and the total across files matches your input exactly. Import the first chunk as a test before emailing all of them.
The verify step deserves its emphasis. Sending seven email attachments and discovering chunk four was the one over the recipient's limit — after the others imported — is a self-inflicted wound the plan screen exists to prevent. Check the estimated sizes against the actual limit you are fighting.
The arithmetic of a clean split
Row-count splitting is integer arithmetic, and seeing it written out removes the mystery. With R data rows in the input and C as your rows-per-chunk setting, the number of chunks is the ceiling of R ÷ C. The first R mod C-less chunks get C rows each if the division is even; when it is not, the final chunk gets the remainder. The complete formula set:
chunks = ceil(R / C)
even = floor(R / C) — chunks of exactly C rows
last = R − (chunks − 1) × C — rows in the final chunk
lines per file = 1 header + C data rows (last: 1 + last)Size mode adds one estimation layer. The tool samples the file's rows to compute an average bytes-per-row figure, divides the target size by it, and rounds down — always down, because a chunk slightly under target is fine and a chunk over target defeats the purpose. The estimate is then checked against the actual bytes written, and the plan screen shows both numbers so you can see whether the estimate was generous or tight. Rows with wildly varying lengths (a notes column that is empty in some rows and three paragraphs in others) make any size estimate a forecast rather than a guarantee; the tool handles this by reporting actual sizes per chunk after generation.
There is also the balanced-chunks mode for the job we see most often after email: a recipient who can import files up to some limit and wants roughly equal parts. Give it the number of parts — nine, for a nine-person team, each importing their slice — and the tool distributes rows as evenly as integer math allows: with 10,000 rows and nine parts, that is eight parts of 1,112 rows and one of 1,102. Close to even beats exactly even when exactness would create a tenth part nobody asked for.
Worked example: 10,000 rows, seven files
The canonical job: a 2.4 MB export with one header row and 10,000 data rows, needed in pieces of at most 1,500 rows for a CRM import that accepts 1,500-record batches. (Names and limits disguised, arithmetic real.)
Input
orders.csv — 10,001 lines (1 header + 10,000 data rows), 2.4 MB total Average row length: 2,400,000 ÷ 10,001 ≈ 240 bytes Mode: rows per chunk = 1,500
Output
chunks = ceil(10,000 / 1,500) = 7 part-1.csv … part-6.csv : 1,500 data rows each (1,501 lines with header) part-7.csv : 1,000 data rows (1,001 lines with header) Verification: 6 × 1,500 + 1,000 = 10,000 data rows — matches input exactly. Total downloaded lines across files: 7 headers + 10,000 rows = 10,007. Estimated size per full chunk: 240 × 1,500 ≈ 360 KB. Final chunk ≈ 240 KB.
Check the arithmetic yourself, because it is the kind you should demand from any splitter: six full chunks of 1,500 rows carry 9,000 rows, leaving 1,000 for the seventh. Seven headers travel with the download. Nothing else changes — the first line of part-2.csv is row 1,501 of the original, unrenumbered, untouched.
Now the same file against a size limit, because the two modes answer different problems. Target: chunks under 500 KB for an upload form. The estimator computes 500,000 ÷ 240 ≈ 2,083 rows per chunk, and the plan becomes five chunks: four at roughly 2,083 rows and a final one at 10,000 − 4 × 2,083 = 1,668 rows. Each lands near 480–500 KB. When the notes column makes some rows ten times longer than average, the actual sizes spread out — which is exactly why the tool reports actual sizes instead of pretending the estimate was destiny.
Headers, quoted fields, and the line-break trap
Two format facts make naive splitting dangerous, and both come from RFC 4180. First, the header problem: a chunk without the header row is a file whose first data row becomes the column names, silently — the worst kind of corruption, because everything still opens. The tool copies the original header byte for byte into every chunk, including headers that contain commas inside quotes or exotic column names.
Second, the line-break problem, which is subtler. CSV records are separated by CRLF line breaks, but a field wrapped in double quotes may contain a line break as data. A customer note reading agreed to the terms — see attached, spread across two physical lines inside quotes, is one field of one row. The splitter's parser tracks quote state character by character, so it counts that as one record and never cuts inside it. The naive approach — split every 1,500 newline-delimited lines, as quick scripts and the split utility do — happily slices through the middle of the quoted note, producing two files that are both unparseable by any standard reader. If your file has no quoted newlines, both approaches agree; if it has even one, only the parser-aware approach is correct. Since you generally cannot know whether an arbitrary export contains quoted newlines without reading it, the safe default is the tool that assumes they exist.
Split by rows or by size: which mode when
The two modes optimize for different constraints, and choosing consciously saves a re-run.
| Constraint you actually have | Mode | Why |
|---|---|---|
| Importer accepts N records per batch | Rows per chunk | The limit is literally a record count — 1,500-row chunks match it exactly |
| Email or upload form caps file size | Target size | The limit is bytes; size mode estimates rows to fit under it |
| Several people each take a slice | Number of chunks | Balanced mode divides the work evenly, remainder to the last part |
| Rows vary wildly in length | Rows per chunk | Size estimates wobble with heterogeneous rows; row counts stay exact |
| Recipient reassembles the file afterward | Rows per chunk | Concatenating chunks minus duplicate headers reconstructs the original exactly |
One asymmetry worth knowing: row mode guarantees exact row counts and merely estimates sizes; size mode targets sizes and derives row counts. Whichever number is your hard constraint is the one you want the mode to control directly.
Who splits CSVs, and what for
The splitter's audience is anyone whose data has to fit through a pipe narrower than the file.
- Operations staff emailing daily exports through attachment limits — the highest-volume use, usually as zip-of-chunks rather than one giant compressed file, because recipients want importable parts.
- CRM and ERP administrators feeding import wizards that cap records per run, where 1,500-row batches turn a failed 60,000-row import into a 40-step checklist that actually completes.
- Analysts working around Excel's 1,048,576-row worksheet ceiling, splitting monster exports into spreadsheet-sized pieces rather than reaching for a database.
- Developers sending fixture data through code-review tools and repositories that choke on multi-megabyte diffs.
- Data entry teams dividing a cleanup job across people — each editor gets their chunk, and balanced mode keeps the workload visibly fair.
- Researchers sharing datasets with collaborators whose institutions block file-sharing services, leaving email as the only sanctioned channel.
The common shape: a transfer constraint that arrived from outside, imposed by an email system, an import wizard or an institutional policy. Splitting is not a data transformation — the data does not change — it is packaging. That is also why the tool refuses to renumber or reformat anything: packaging that edits contents is not packaging.
Splitter versus zipping versus a cloud link
Three ways past a size wall, and the right one depends on who is receiving.
| Approach | Best when | Weakness |
|---|---|---|
| Zip the whole file | The limit is about attachment bytes and the recipient just needs the file | CSV compresses well (often 80–90%), but a 60 MB export may still exceed the cap after compression; recipient must reassemble before any partial import |
| Split into chunks | The recipient imports in batches, multiple people take slices, or the limit is per-record | More files to manage; headers multiply; someone must track which parts are done |
| Cloud storage link | Both sides can use Drive/Dropbox/WeTransfer and policy allows it | Often blocked in exactly the locked-down environments that also cap attachments; the file leaves your control |
Two details that tip real decisions. CSV compresses remarkably well — repeated headers, similar rows and low entropy mean a zip routinely lands around a tenth of the original size — so if the wall is 25 MB and your export is 60 MB, compression alone sometimes clears it. And chunking plus zipping combines cleanly: split into importable parts, then zip the parts folder, and you get both batch-friendly files and a smaller transfer. The tool's zip download is that combination with one click. What it deliberately does not do is generate a self-reassembling archive — those get stripped by mail servers that distrust executable attachments, which is most of them.
If the recipient can reassemble files themselves, note the one-rule recipe: concatenate all chunks and delete the extra header lines (all but the first), and the original file returns byte for byte. No transformation was ever applied, so no reverse transformation is needed.
How to eat a two-gigabyte file: streaming, not swallowing
The invisible engineering question under every splitter is memory architecture, and the naive answer dies quietly. Read the whole file into one string, split it, write the pieces: for a browser, that means the file's bytes become a JavaScript string — two bytes per character — and then an array of chunk strings on top. A 2 GB export becomes roughly 4 GB of string before the first cut lands, and tabs give up somewhere near that mark, usually without an error message worth the name.
| Architecture | Memory footprint | What dies at | Where you meet it |
|---|---|---|---|
| Whole-file read, then split | Two to four times the file size once strings and chunk arrays exist | The browser tab itself, around a few GB — mobile earlier | Quick scripts and small files, where it is fine |
| Line-by-line streaming | One line at a time | Nothing memory-wise — but it corrupts quoted newlines on contact | Unix split, naive scripts, most one-off helpers |
| Parser-state streaming | One read slice plus the current chunk — tens of MB, constant | Nothing short of disk size | This tool's approach |
The streaming version works in slices: the file is read a few megabytes at a time through the browser's file API, parsed incrementally, and each output chunk is finalized the moment it fills. Memory usage stays pinned at roughly one slice plus the chunk under construction plus the header — the same tens of megabytes whether the input is 200 MB or 2 GB. Cost scales with chunk size, which you chose, instead of file size, which you did not.
The hard part is the boundary between slices, and it is the same hard part as the quoted-newline trap two sections up. A quoted field can span the edge of one read and the start of the next exactly as it can span two physical lines, so the parser carries its state — inside quotes or not — across every slice boundary. That carried boolean is the entire difference between a splitter that handles a three-paragraph shipping note and one that corrupts it at an arbitrary byte offset. Correctness at slice boundaries is not a bonus feature; it is the reason the architecture works at all.
Your file never touches a server
The files that need splitting tend to be the files you least want to hand around: full customer exports, payroll dumps, complete transaction histories. An upload-based splitter means the complete sensitive file goes to someone else's disk, gets cut there, and downloads back — a full round trip through a third party for the sake of an operation your own machine does faster. This tool reads the file with the browser's local file API, splits it in memory, and generates the zip in the browser too. No upload. No storage. No terms-of-service paragraph about how your data is briefly retained for quality purposes.
The zip generation happens through in-browser compression, which also keeps the whole operation quick: there is no upload wait on a 60 MB file, no queue, and no download-the-result wait either. For people in restricted networks — hospitals, banks, government offices, the exact places with the attachment limits — a tool that works without the network leaving the building is not a nicety. It is the requirement.
FAQ about splitting CSV files
The questions that arrive whenever someone meets a size limit.
Does every output file keep the header row?
Yes. Each chunk starts with the original header row exactly as it appeared, so every file is independently importable — open any one of them in Excel, a database import wizard or another tool, and the columns resolve correctly. The header is copied, never invented, so multi-line headers and unusual column names survive byte for byte.
Can I split by file size instead of row count?
Yes. Size mode divides your target size by the average bytes per row to estimate rows per chunk, then splits on that row boundary so it never cuts a record in half. Row boundaries are the only safe place to cut a CSV — a byte-precise split would slice through quoted fields and corrupt both halves.
What if my CSV has line breaks inside quoted fields?
Those are handled correctly, and this is the splitter's main technical advantage over naive alternatives. A quoted field containing a newline is one field in one row, so the parser tracks quote state and only counts a new row when a record actually ends. Scripts that split on every line break will silently corrupt such files — chunk boundaries land mid-field and both output files become unparseable.
How many chunks can it create?
The practical ceiling is your patience, not the tool — thousands of chunks compute fine. The zip download is generated in the browser, so a 10,000-chunk job is really a question of whether you want a 10,000-file archive. For most jobs (5–50 chunks) everything finishes in seconds.
Does splitting change or renumber my data?
No. Rows are copied verbatim, in original order, into consecutive chunks. No renumbering, no reformatting, no delimiter conversion, no quote rewriting. The only thing the tool adds is the header line at the top of each file. Chunk one ends with row 1500, chunk two begins with row 1501 — always.
How large a file can it split?
Files in the tens of megabytes split in seconds, and the practical limit is your machine's memory rather than any quota. The parser is streaming-friendly for row counting, so even exports that make spreadsheet software visibly sweat — the kind with hundreds of thousands of rows — process without drama.
Can it split files with semicolons, tabs or other delimiters?
Yes. Delimiter detection identifies commas, semicolons and tabs automatically, and you can override it manually for unusual cases. The delimiter affects where rows end and where fields begin, so correct detection is what makes the quoted-field logic reliable in the first place.
Is my file uploaded to split it?
No. The file is read locally with the browser's File API, chunks are assembled in memory, and the zip archive is generated in your browser as well. Nothing is transmitted — a 200 MB export crosses no network boundary at any point, which is both faster and safer than an upload-based splitter.
Tools that go well with this one
Splitting pairs naturally with the steps around it. Deduplicate before splitting so chunks carry unique records — the CSV Deduplicator runs on the full file first. Anonymize sensitive columns before the chunks travel, with the CSV Data Anonymizer, especially when chunks are headed to different recipients. And when the destination is an API or pipeline rather than an import wizard, converting chunks to JSON with the CSV to JSON Converter after splitting keeps each piece self-describing.
The reverse job — many files becoming one — also lives in the neighborhood: run chunks back through the deduplicator after teammates return edited slices, to catch rows that drifted between parts during cleanup.
References
Format specifications and the database import documentation referenced above:
Sources and further reading
- RFC 4180 — Common Format and MIME Type for Comma-Separated Values (CSV) Files(rfc-editor.org)
- PostgreSQL Documentation — COPY (CSV import)(postgresql.org)
- MySQL Reference Manual — LOAD DATA Statement(dev.mysql.com)
- MDN Web Docs — Blob and File API reference(developer.mozilla.org)
We cite primary sources (standards bodies, government agencies, official documentation) wherever they exist so you can verify every number on this page yourself.