BLOG / GUIDE · 2026-04-27 · 9 min

How to split a large CSV file into smaller files

Five practical ways to split a large CSV — the Unix split command, PowerShell, pandas, Excel Power Query, or a browser tool. With the header-row trick most splitters skip.

The short answer. For a quick split in the browser, paste or drop your file into the text file splitter — pick a line count or byte size, hit split, download the zip. On macOS or Linux, split -l 10000 input.csv chunk_ writes one file per 10,000 lines. On Windows, PowerShell's Get-Content with a stream filter handles the same job. Python with pandas is the right call when you need to keep the CSV header in every chunk, which most simple splitters — including ours — do not do automatically.

Why split a CSV at all?

Four reasons cover most of the real-world cases.

  • Upload limits. Most web apps cap CSV imports at 25 MB, 100,000 rows, or some equally arbitrary number. A 2 GB export from a CRM has to be cut down before it'll go in.
  • Memory. Loading a 5 GB CSV into Excel or pandas crashes on most machines. Splitting it into 50 chunks of 100 MB makes the data tractable for downstream processing.
  • Parallelisation. Some ETL pipelines run faster on many small files than one big one — each chunk can be processed on its own thread or worker.
  • Sharing. Email and Slack file limits, version-control friendliness, anything where a single huge file is awkward.

Before you pick a method, there is one decision that separates "easy" from "annoying": do you need the CSV header row in every chunk?

Most downstream importers need it. A naive split — whether split, PowerShell, or a browser-based line splitter — just chops the file by line count or byte size and leaves the header sitting in chunk 1 only. To put the header in every chunk you either need a tool that knows about CSV semantics (pandas, csvkit, dedicated commercial splitters) or you post-process the naive output. Both are fine. Just know which path you're on before you start.

How do you split a CSV on macOS or Linux?

The split command has been there since the Unix V7 days and still wins on speed.

Split by line count.

split -l 10000 input.csv chunk_

Writes chunk_aa, chunk_ab, chunk_ac, …, each with 10,000 lines. Add --additional-suffix=.csv to keep the file extension. The default suffix uses two letters, enough for 676 files; -d switches to numeric suffixes if you prefer.

Split by file size.

split -b 50M input.csv chunk_ --additional-suffix=.csv

Use this when the downstream importer cares about megabytes, not rows. Beware: -b doesn't respect line boundaries. The last line of each chunk and the first line of the next can be the same row, halved. Pass -C 50M instead — that splits at line boundaries while staying under the size cap.

Keep the header in every chunk.

HEADER=$(head -n 1 input.csv)
tail -n +2 input.csv | split -l 10000 - chunk_
for f in chunk_*; do
    echo "$HEADER" | cat - "$f" > "${f}.csv" && rm "$f"
done

Three steps: grab the header, split everything else, prepend the header to each chunk. Ugly, but it is the standard recipe and it works on any Unix machine without extra tools.

How do you split a CSV on Windows with PowerShell?

No split command, but PowerShell can do the same job. Two patterns cover most needs.

Split by line count, header preserved.

$lines = 10000
$file  = "input.csv"
$header = Get-Content $file -TotalCount 1
$i = 0
Get-Content $file | Select-Object -Skip 1 |
    ForEach-Object -Begin { $buf = @() } -Process {
        $buf += $_
        if ($buf.Count -ge $lines) {
            $header, $buf | Set-Content "chunk_$i.csv"
            $buf = @(); $i++
        }
    } -End {
        if ($buf.Count) { $header, $buf | Set-Content "chunk_$i.csv" }
    }

Slow for very large files because Get-Content reads line by line and PowerShell's pipeline isn't free. For files bigger than a few hundred megabytes, the .NET StreamReader route is roughly an order of magnitude faster — reach for it if speed matters and you're comfortable with C#-flavoured PowerShell.

On Windows 10 and later, the simpler answer is often "install WSL and use split". The Unix one-liner runs at native speed under WSL and avoids the PowerShell pipeline overhead entirely.

How do you split a CSV in Python with pandas?

The right tool when you need semantic awareness — headers, column types, encoding handling — without a custom script.

import pandas as pd

chunk_size = 10000
for i, chunk in enumerate(pd.read_csv("input.csv", chunksize=chunk_size)):
    chunk.to_csv(f"chunk_{i:04d}.csv", index=False)

A few features come for free:

  • Each output file has the header row, automatically.
  • pandas streams the input — it never loads the whole CSV into memory, so a 50 GB file works on a laptop.
  • Quoted fields with embedded newlines are handled correctly. A naive line-based split breaks rows whose values contain \n; pandas doesn't.
  • Encoding can be set explicitly: pd.read_csv("input.csv", encoding="utf-8-sig") handles BOMs from Excel exports.

The trade-off is the Python install — not a problem on a data team's machine, but overkill for a one-off split.

Can you split a CSV inside Excel?

Yes, but only for small files. Excel's hard ceiling is 1,048,576 rows per sheet, and many machines crawl long before that. The least-bad way involves Power Query:

  1. Data → Get Data → From File → From Text/CSV, point at the file, click Transform Data.
  2. In Power Query, add an Index column starting at 0.
  3. Add a custom column: Number.IntegerDivide([Index], 10000). That tags each row with a chunk number.
  4. Group by the chunk column, or filter and export each group as a separate file.

Honestly, for anything over 100,000 rows, the command line is faster, the browser tool is faster, and the result is the same. Excel is the right answer only when the CSV is small and the workflow already lives in a spreadsheet.

How do you split a CSV online, instantly?

Open the text file splitter. Paste the content (or drop the file in). Pick a mode: by line count, by byte size, by a fixed number of equal parts, by character count, by a delimiter, or by a regex. Click Split. Each chunk appears as its own panel with a preview; the Download ZIP button packages them.

  • Nothing uploads. The tool is JavaScript that runs in your browser. Open DevTools → Network and run a split — you'll see zero outbound requests carrying your data. The ZIP is built in-memory using JSZip and downloaded directly from the tab.
  • Six modes cover most splits: Parts (equal halves, thirds, etc.), Lines, Bytes (KB / MB), Chars, Delim, and Regex.
  • Honest limitation. The tool does not understand CSV semantics. It splits text by your chosen rule and leaves the header row in chunk 1 only. If your downstream importer needs the header in every chunk, post-process the ZIP or use the CLI / pandas recipes above. We may add a "Keep header" toggle later; until then, this is a real gap and we want you to know.
  • Practical ceiling. The bottleneck is not the splitter — it is the clipboard and browser memory. Once you are feeding very large files through paste, the OS itself starts to lag, and the in-tab JSZip step has to hold the whole result in memory. For multi-gigabyte files, drop down to the command line.

Which method should you use?

Your situationBest method
One-off CSV under ~200 MB, no header requirementBrowser tool
One-off CSV, header needed in every chunkpandas or the Unix header-preserving recipe
macOS or Linux, fast and simplesplit -l
Windows, occasionalPowerShell, or WSL + split
Data team, repeatable pipelinepandas (or csvkit's csvsplit)
Multi-gigabyte fileCommand line, no contest
Quoted fields with embedded newlinespandas — line-based splitters will break these rows
Workflow already lives in Excel, file is smallPower Query
Sensitive data, privacy mattersBrowser tool or local command line — never an upload-based site

Frequently asked questions

How big can a CSV file be before I need to split it?

Depends on what comes next. Excel caps at 1,048,576 rows per sheet; many BI tools cap imports at 25 MB or 100,000 rows; APIs commonly limit posts to a few megabytes. As a rough rule, if a file is over 100 MB or over 500,000 rows and your downstream consumer isn't pandas / Spark / a database, splitting it pays off.

Will splitting by line count break rows that contain newlines inside quoted fields?

Yes — if a value like "Hello\nWorld" straddles a chunk boundary, both halves end up broken. Naive line splitters (split, PowerShell line-counts, our browser tool) don't know about quoted fields. The cure is pandas or any CSV-aware library that parses fields before counting rows. If your data has embedded newlines (export from a CRM with multi-line notes, for example), use a CSV-aware tool.

How do I keep the CSV header in every chunk?

Three options. (1) Use pandas — chunk.to_csv() writes the header automatically. (2) Use the Unix header-preserving recipe above (head -n 1tail -n +2 | splitcat header + chunk). (3) Use a dedicated CSV splitter (csvkit's csvsplit, or a commercial GUI). The joinlines browser tool does not preserve headers yet — mentioned in the limitations above.

What's the difference between splitting by bytes and by lines?

Byte-based splits hit exact size targets, useful when the downstream importer has a "25 MB max" rule. Line-based splits respect row boundaries, useful when the data is row-oriented. The Unix split -C 50M is the best of both — cap by bytes, break at line boundaries. The browser tool's Bytes mode is codepoint-safe (no broken UTF-8 characters) but does not respect row boundaries — for CSV row integrity, use Lines mode instead.

Can I split a CSV by a column value, e.g. one file per country?

Not with any of the byte-or-line splitters. This is a "GROUP BY" operation, not a sequential chop. pandas handles it cleanly:

import pandas as pd
df = pd.read_csv("input.csv")
for value, group in df.groupby("country"):
    group.to_csv(f"out_{value}.csv", index=False)

The awk equivalent works for simpler files: awk -F, 'NR==1{header=$0; next} {print (NR==1?header:$0) > "out_"$3".csv"}' input.csv.

Is it safe to split a sensitive CSV in a browser tool?

Only if the tool runs entirely in the browser. Open DevTools, switch to the Network tab, run a split, and watch for outbound requests. If you see one carrying your data, the page sent it to a server. The joinlines splitter makes zero requests after the page loads — verifiable in DevTools, every time.

— the joinlines team, 2026-04-27

§ — PRIVACY Your text never leaves your browser. No upload, no account, no logs on what you paste.
PRIVACY PAGE ↗