Reference
CSV Limits: Maximum Rows, Columns and Field Length
What the CSV format limits, what Excel, Google Sheets and common import tools limit, and what RowSlice’s own tools handle — every figure with the source it came from.
Vendor figures last checked
In short: the CSV format has no limits. RFC 4180, the document that describes CSV, sets no maximum file size, row count, column count or field length, so every number on this page belongs to a program that reads or writes CSV rather than to CSV itself. The first one most people meet is Excel, whose worksheet holds 1,048,576 rows and 16,384 columns. RowSlice’s tools read a file a few megabytes at a time and are limited by free disk space rather than by a row count, except where a row has to be recognised again later — Remove Duplicates, Compare, the Analyzer and the Validator. Those four ceilings are listed below, each read from the constant in the code that enforces it.
What RFC 4180 Defines, and What It Does Not
RFC 4180 is the closest thing CSV has to a specification. It is an Informational document rather than a standard, nothing enforces it, and it is what RowSlice’s parser follows. It is also the answer to the question people most often ask about CSV size, because it declines to answer it.
| What people ask about | What RFC 4180 says |
|---|---|
| Maximum file size | Nothing. A CSV is plain text and can be as large as the disk holding it. |
| Maximum number of rows | Nothing. The document does not count records. |
| Maximum number of columns | Nothing, beyond asking that every record in a file hold the same number of fields. |
| Maximum length of a value | Nothing. |
| Character encoding | Not fixed. RFC 4180 registers the media type text/csv with an optional charset parameter, which travels outside the file; nothing inside a CSV records which encoding wrote it. |
| Delimiter | A comma. Semicolon, tab and pipe files are common and are outside the document. |
| Quoting | A field holding a comma, a double quote or a line break is wrapped in double quotes, and a double quote inside such a field is written twice. |
| Line endings | Records are separated by CRLF, and the last record may or may not end with one. |
| Header row | Optional, and signalled by the media type’s header parameter rather than by anything in the file. |
The size limits a CSV does meet belong to whatever opens, stores or carries it — a program’s memory, an email attachment cap, a FAT32 drive, an upload form — and the guide to CSV file size limits gives each one in megabytes or gigabytes, with its source.
Spreadsheet Limits
| Program | Grid limit | What happens past it | Source |
|---|---|---|---|
| Excel (.xlsx, .xlsm) | 1,048,576 rows and 16,384 columns per worksheet | Excel loads the rows that fit and warns that the file is not loaded completely. Saving at that point writes the truncated version over the original. | Microsoft |
| Excel 97–2003 (.xls) | 65,536 rows and 256 columns per worksheet | The same truncation, at a far lower number. | Microsoft |
| Excel Data Model | 1,999,999,997 rows per table | Rows load well past the worksheet limit, but they cannot be scrolled or edited in a grid. | Microsoft |
| Google Sheets | 20 million cells, counted across every tab, or 100 MB per spreadsheet created in or converted to Sheets | “This file is too large to import directly into Google Sheets”. | Google, announcement |
| Apple Numbers | 1,000,000 rows and 1,000 columns per table, the figure Apple gives for importing and exporting Excel spreadsheets | Compare the row count Numbers shows against the file’s real count: if the two differ, the import stopped early and the file has to be split. | Apple |
Excel has a second limit that is not printed on the grid: memory. Microsoft’s guide to Excel’s resource errors states that “in any 32-bit application, there’s a 2-GB limitation”, while “the 64-bit version allows all available physical RAM on the machine to be used”; a later change doubled 32-bit Excel’s allowance to 4 GB on 64-bit Windows. A CSV large enough to hit that is almost always over the row limit as well. Excel’s row limit explained covers what happens to the rows that do not load.
If a CSV may be over the row limit, count its rows first rather than opening it in Excel; past 1,048,575 data rows, split the CSV into parts of 1,000,000 rows, each starting with the header, and every part opens whole.
Excel Changes Values Before It Runs Out of Rows
| What Excel limits | Figure | What it does to a value | Source |
|---|---|---|---|
| Characters in one cell | 32,767 | Text past the limit is not kept. RowSlice measured a longer value in Excel 2021 spilling into a new row and shifting every column after it, rather than producing an error. | Microsoft, and RowSlice’s own test |
| Significant digits kept for a number | 15 | Digit 16 onwards is replaced with a zero, so a 16-digit card number comes back with its last digit turned into a 0, and a long ID is displayed as something like 4.5E+15. | Microsoft |
The 15-digit limit applies only once Excel has decided a value is a number, which is why a CSV converted to a real .xlsx workbook with every value already written as text keeps every digit. Stop Excel turning long numbers into 4.5E+15 and why Excel removes leading zeros cover the two cases separately.
Google Sheets Counts Cells, Not Rows
Google’s limit is 20 million cells, counted as rows multiplied by columns across every tab of one spreadsheet, so how many rows fit depends on how wide the file is. The header row counts as a row: RowSlice’s CSV Analyzer reports a file’s data rows and columns, so add one for the header and multiply. The table below is that division; it assumes one tab and no other data in the spreadsheet.
| Columns in the file | Rows that fit in 20 million cells, header included |
|---|---|
| 5 | 4,000,000 |
| 10 | 2,000,000 |
| 20 | 1,000,000 |
| 50 | 400,000 |
| 100 | 200,000 |
Google also caps a spreadsheet created in or converted to Sheets at 100 MB, so a file with long values can fail before it reaches 20 million cells. Google’s help page gave both figures when we read it on 10 October 2026. The cell limit was 10 million until Google doubled it in a rollout that began on 10 September 2026, so older references still give 10 million. What to do when a CSV is too large for Google Sheets covers the options when a file does not fit.
Import Tools
Import limits are published per product and are stated in rows, in megabytes, or in both. These were read from each vendor’s own documentation on October 10, 2026.
| Tool | Published limit | Source |
|---|---|---|
| Shopify product import | “Your product CSV can’t exceed 15 MB”, and the file must be saved as UTF-8 | Shopify |
| HubSpot import, paid tiers | 512 MB and 1,048,576 rows per file, fewer than 1,000 columns, 10,000,000 rows per day | HubSpot |
| HubSpot import, free tools | 20 MB per file, fewer than 1,000 columns, 500,000 rows per day | HubSpot |
| Klaviyo list upload | “Your CSV file must be 50 MB or less” | Klaviyo |
| Mailchimp contact import | Over 200 MB, or about one million contacts, “may cause import errors” | Mailchimp |
| Salesforce Data Import Wizard | 50,000 records per run | Salesforce |
| Salesforce Data Loader | 150 million records per run | Salesforce |
| Google BigQuery load job | 4 GB per compressed CSV; 5 TB uncompressed | Google Cloud |
How to split a CSV to fit an import limit covers more products, the daily allowances some of them add on top, and how to work out the right part size.
What RowSlice’s Own Tools Handle
RowSlice reads a file in chunks of a few megabytes in the browser and writes results to the browser’s storage on the visitor’s own disk, so memory use does not grow with file size and most tools have no row limit at all. Four of them — Remove Duplicates, Compare, the Analyzer and the Validator — have to recognise a row again after it has gone past, and each keeps a 64-bit fingerprint per distinct row or key in memory, which is where their ceilings come from. Every figure below is the constant that enforces it, in the file that holds it.
| Tool | Limit | What happens past it | Where the figure lives |
|---|---|---|---|
| CSV Viewer | 13,107,200,000 rows: an index of at most 200,000 row offsets (1.6 MB) with a stride that doubles to at most 65,536 rows | A request for a row past that is refused, naming the highest row the index can reach. Split or filter the file first. | MAX_ENTRIES, MAX_STRIDE in src/lib/engine/view.js |
| CSV Viewer, UTF-16 files | Refused, whether or not the file carries a byte order mark | The viewer finds rows by their position in bytes, which UTF-16 does not line up with. A file with no byte order mark is refused too when the zero bytes in its first 4,096 bytes nearly all fall on the same side of each byte pair, which is what UTF-16 does and single-byte text never does. Convert the file to UTF-8 first. | HEAD_BYTES, looksUtf16 in src/lib/engine/view.js |
| CSV Viewer, search | 500 matching rows listed | Every matching row is still counted, so the count and the list are different numbers on purpose. | VIEW_SEARCH_LIMIT in src/scripts/tool-ui.js |
| Remove Duplicates, keeping the first copy | 33,554,432 distinct rows per run | The run stops, names the number it had reached, and saves no partial result. | FingerprintSet in src/lib/engine/hash.js |
| Remove Duplicates, keeping the last copy | 8,388,608 distinct rows per run, and the file is read twice | The same stop. This mode has to remember where each row last appeared, not only that it appeared, which is why its ceiling is a quarter of the other one. | FingerprintMap in src/lib/engine/hash.js |
| Compare Two CSV Files | 8,388,608 distinct keys across both files per run; the column-by-column before-and-after detail is shown for at most 100 changed rows, or fewer if those rows together run past 1,048,576 characters | The run stops at the key ceiling, names the number it had reached and saves no partial result. Reaching the detail limit stops nothing: the added, removed and changed CSVs are still written in full. | FingerprintMap in src/lib/engine/hash.js; maxSamples, SAMPLE_CHAR_BUDGET in src/lib/engine/compare.js |
| CSV Analyzer | 33,554,432 distinct rows for the exact duplicate count; 262,144 distinct values per column | A column that passes 262,144 shows its distinct count with a trailing +, which is a floor rather than a total. | DISTINCT_SLOTS in src/lib/engine/profile.js |
| CSV Validator | 33,554,432 distinct rows for the exact-duplicate check, and the same again for the values of a chosen ID column | The run stops and names the number it had reached. The validator keeps no per-column distinct count at all, so no other check has a ceiling. | FingerprintSet in src/lib/engine/hash.js, used from src/lib/engine/profile.js |
| Take a Sample from a CSV | 1,000,000 rows for a random sample | A larger request is refused before the run starts. The other three modes — the first n rows, every nth row and a percentage — hold nothing in memory and have no limit. | MAX_RANDOM_ROWS in src/lib/engine/sample.js |
| Sample CSV File Generator | 100,000,000 rows, or 20 GB by size; 1 KB minimum | A larger request is refused with the maximum in the message. | LIMITS in src/lib/engine/generate.js |
| Split CSV by Column Value | 10,000 output files per run | The run stops and asks for a column with fewer distinct values, such as a region, category or status. | maxFiles in src/lib/engine/jobs.js |
| Convert CSV to Excel | Excel’s own: 1,048,576 rows per sheet, 16,384 columns, 32,767 characters per cell | Rows past the first sheet continue on further sheets with the header repeated; columns past 16,384 are dropped and cells are cut, and both counts are reported. | SHEET_ROW_LIMIT, SHEET_COLUMN_LIMIT, CELL_CHAR_LIMIT in src/lib/engine/xlsx.js |
| Convert JSON to CSV | 1,024 columns in the header; nested objects flattened 20 levels deep | Keys past 1,024 are left out and the run says so. Past 20 levels the rest of that branch goes into one cell as JSON text. | MAX_COLUMNS, FLATTEN_DEPTH in src/lib/engine/json.js |
| Every tool | 64 MB of text in one CSV record | The parser reports a runaway row, which in practice means a quote that was opened and never closed. | maxRowChars in src/lib/engine/parser.js |
| Every tool | Free disk space and the browser’s per-site storage quota | Firefox reports about 10 GB to a site. This is what stops a very large job, not a row count. | Reported by the browser |
The largest run RowSlice has measured is a 1 GB file of 25 million rows split in Firefox with every row intact. Tools with no entry above — splitting by rows, filtering rows, merging files, writing JSON out of a CSV and converting the encoding — keep nothing from one row to the next except the counts they report, so they have no row ceiling of their own.
Encodings
A CSV does not record its own encoding, so every program that opens one is guessing. Which encoding a file is in decides whether accented characters survive, and whether RowSlice can page through the file row by row at all.
| Encoding | What it is | What it means for a CSV |
|---|---|---|
| UTF-8 | One to four bytes per character, covering all of Unicode. The first 128 characters are one byte each and identical to ASCII. | The safe choice, and what every RowSlice tool writes. Excel opened by double-click does not assume UTF-8 unless the file carries a byte order mark. |
| UTF-16, little or big endian | Two bytes for every character up to U+FFFF and four for the rest. Every ASCII character carries a zero byte alongside it. | Roughly doubles the size of mostly-English data, and character positions no longer line up with byte positions — which is why the CSV Viewer refuses UTF-16 rather than showing it wrongly. |
| Windows-1252 | One byte per character and 256 characters in total; the Windows ANSI code page in Western European locales. | Cannot hold a character outside its 256. A Windows-1252 file read as UTF-8 shows a replacement character for every accented letter; a UTF-8 file read as Windows-1252 shows José as José. |
A byte order mark, or BOM, is a short signature at the very start of a file naming the Unicode encoding that follows. It is not part of the data, and a program that does not recognise one reads its bytes as characters and glues them to the first column name.
| First bytes of the file | Encoding it announces |
|---|---|
EF BB BF | UTF-8 |
FF FE | UTF-16, little endian |
FE FF | UTF-16, big endian |
FF FE 00 00 | UTF-32, little endian |
00 00 FE FF | UTF-32, big endian |
Excel wants a UTF-8 BOM on a file it is asked to open by double-click; JSON readers reject one, which is why RowSlice’s CSV to JSON converter never writes one and its JSON to CSV converter writes one by default. UTF-8, UTF-16 and Windows-1252 explained covers how to tell which encoding a file is in from what is on screen.
Delimiters
RFC 4180 names the comma and nothing else, but the character that separates fields varies by region and by the program that wrote the file. Excel splits a double-clicked CSV on the Windows list separator, which is a semicolon wherever the decimal separator is a comma — so the same file opens in columns on one machine and in a single column on the next. RowSlice detects comma, semicolon, tab and pipe automatically, and the UTF-8 converter changes a file’s delimiter as well as its encoding.
Definitions
| Term | What it means |
|---|---|
| Record | One logical row of a CSV. A record is not the same as a line: a quoted value may contain a line break, so one record can span several lines of the file. A CSV of 1,000 records may have more than 1,000 lines. |
| Line | One run of text in the file ending at CRLF or LF. Counting lines with wc -l counts lines, not records, which is why the two numbers disagree on files that contain quoted line breaks. |
| Data row | A record other than the header row. A CSV with a header and 1,000 data rows holds 1,001 records. |
| Field | One value inside a record. RFC 4180 calls it a field; a spreadsheet calls the same thing a cell once the file is open. |
| Delimiter | The character separating fields inside a record: a comma in RFC 4180, and in practice also a semicolon, a tab or a pipe. It is not recorded anywhere in the file. |
| Byte order mark | Two to four bytes at the very start of a file naming the Unicode encoding that follows. It is metadata, not data, and a reader that does not recognise it shows it as characters. |
| Cell, for a Google Sheets limit | One position in the spreadsheet grid. Google counts its limit in cells — rows multiplied by columns, across every tab — so the number of rows that fit depends on how many columns the file has. |
The first two of those are why two programs report different counts for the same file. RowSlice’s CSV Analyzer reports all three numbers — data rows, CSV records and physical lines — for a file of any size, and how to count the rows in a CSV explains why they differ.
FAQ
Questions About CSV Limits
What is the maximum number of rows in a CSV file?
A CSV file has no maximum number of rows. RFC 4180, the document that describes the format, does not count records and sets no upper bound, so the number of rows a CSV may hold is limited only by the disk it is stored on. The limit most people run into belongs to Excel: one worksheet holds 1,048,576 rows, header row included, and Excel loads that many from a longer file and warns that the file was not loaded completely.
How many columns can a CSV file have?
The format sets no column limit; RFC 4180 asks only that every record in a file hold the same number of fields. Programs do set one: an Excel worksheet stops at 16,384 columns and HubSpot’s import requires fewer than 1,000. For Google Sheets, Google’s help page now gives only a cell limit and a size cap, 20 million cells or 100 MB per spreadsheet, so how many columns fit depends on how many rows come with them. RowSlice’s JSON to CSV converter builds a header of up to 1,024 columns from the keys it finds and reports any keys it left out.
How long can a single CSV value be?
RFC 4180 sets no length for a field. Excel cuts a cell at 32,767 characters, and RowSlice measured a longer value spilling into a new row and shifting every column after it rather than producing an error. RowSlice’s own parser reads a single CSV record up to 64 MB of text (maxRowChars in src/lib/engine/parser.js) and reports a runaway row past that, which in practice means an unclosed quote.
Do RowSlice’s tools have a row limit?
Most of them do not. RowSlice reads a file in chunks of a few megabytes and writes results straight to disk, so splitting, filtering, merging and converting have no row ceiling at all — free disk space and the browser’s storage quota decide how large a file can be. The exceptions are the tools that have to recognise a row again later: Remove Duplicates, Compare, the Analyzer and the Validator keep a 64-bit fingerprint per distinct row or key, and the table above gives each ceiling and what happens when a run reaches it.
Where do the figures on this page come from?
Each vendor figure is quoted from that vendor’s own published documentation and the Source column links to the page it came from; they were last read on October 10, 2026. Each RowSlice figure is read from the constant in the code that enforces it, and the table names the file it lives in, so any of them can be checked against the source rather than taken on trust.