Skip to Content
RowSlice

Free Online CSV Compare

Compare Two CSV Files

Last month's export and this month's, the file before a migration and the file after, your system of record against a vendor's list. Match the rows on an ID column and get the added, removed and changed ones as files you can download.

  • Multi-GB files
  • Never uploaded
  • Free, no sign-up

In short: RowSlice's CSV compare tool reads two CSV files in your browser and reports what moved between them: how many rows were added, removed, changed and left alone, which columns changed — with the value before and after — for up to 100 of the changed rows, and which columns exist in only one of the files. Rows are matched on a key column you choose — a customer ID, an email address, a SKU — so the two files can be sorted differently and still line up. The added, removed and changed rows are written to separate CSV files. It is not a line-by-line text diff, and it does not merge the two files or decide which version of a row is correct: it reports what is different and leaves both of your files untouched. Nothing is uploaded.

How to Compare Two CSV Files

  1. Choose or drag in both files, the older one first; if they go in the wrong way round, Swap Old and New puts them right. They are read from your disk instead of uploaded, so even a multi-gigabyte pair is ready in a second.
  2. Choose the column that identifies a record — customer_id, email, an order number, a SKU. Tick more than one if it takes a combination to identify a row.
  3. Leave every shared column in the comparison, or name the columns to compare when some of them are rewritten on every export.
  4. Press Compare Files, read the counts, and download whichever of the result files you need.

What Added, Removed, Changed and Unchanged Mean

Every row of both files lands in exactly one of four buckets, and its key decides which. Take an inventory export run in March and again in April, matched on sku:

skuprice in the March fileprice in the April fileStatus
A-1023200.00250.00Changed
A-102419.9919.99Unchanged
A-1025not in the file12.50Added
A-10267.25not in the fileRemoved

A row is added when its key is in the new file and nowhere in the old one, and removed when its key is in the old file and never turns up in the new one. A key found in both files gives a changed row when at least one compared value differs, and an unchanged row when every compared value is identical, character for character, after whatever ignore-case and ignore-spaces rules you asked for.

Unchanged rows are counted and nothing more: they are already sitting in both of your files, so writing them out a third time would only make the results harder to read. Everything else becomes a file, named after the file it came from — for inventory-march.csv and inventory-april.csv:

FileWhat is in it
inventory-april-added.csvRows of the new file whose key is not in the old file, as the new file has them
inventory-march-removed.csvRows of the old file whose key is not in the new file, as the old file had them
inventory-april-changed.csvThe changed rows as they are now, taken from the new file
inventory-march-changed-before.csvThe same records as they were, taken from the old file, so you can see what each value used to be

A file is written only when it has rows in it, so a run where nothing was removed gives you no removed file at all and the download list is itself part of the answer. On screen you also get the changed rows in detail — the key, the column that changed, the value before and the value after — for up to 100 of them. That list is capped because it is the one part of the run that keeps values in memory; the downloaded files hold every changed row, however many there are. When there are more of them than a spreadsheet will open, open that file in the CSV viewer, which pages through a CSV of any size and can search it for one key.

Neither of your files is modified, and no file combining the two is produced. If what you want is the rows of both files in one file, that is a different job: merge the two CSVs and, when the same record is then in there twice, remove the duplicate rows afterwards.

Choosing the Key Column

The whole result rests on the key. It is how a row in one file is recognised as the same record in the other, and a key chosen badly does not give a slightly worse answer — it gives a confident wrong one, usually a report in which almost everything was removed and almost everything was added.

A key column needs two properties, and both are worth checking rather than assuming:

  • Unique within each file. One row per key, in the old file and in the new one.
  • Stable between the two exports. The value has to survive whatever happened in between. A database ID normally does; a row number, a line position or a sequence the export regenerates on every run does not, and matching on one of those compares row 5,000 with row 5,000 rather than a record with itself.

When no single column is unique, tick several and their values are joined into one key — store_id plus sku, or first name plus last name plus date of birth. Keep the key as short as you can. A column that is part of the key is not a column whose changes get reported: change it and you get a removed row and an added row instead, which is the correct answer to the question that was asked and rarely the one you wanted.

Ignore upper and lower case and Ignore spaces at the start and end of values apply to the key as well as to the values being compared, which is usually what you want for data typed by people. Without them, ANN@SHOP.COM and ann@shop.com are two different keys, so one record is reported as removed and added rather than matched.

If the same key appears more than once in a file, the comparison is ambiguous: there is no way to know which copy belongs with which. The tool keeps the first row for each key, counts the rest and shows you that count. Treat anything above zero as a caution on the whole report. You can check a column before you start — the CSV analyzer gives the number of distinct values in every column next to the number of data rows, and a column where those two numbers are equal is unique — and Remove Duplicates from CSV collapses the repeats when they really are the same record twice.

When the Two Files Have Different Columns

Two exports of the same thing, taken months apart, are rarely identical in shape. A column gets added, two swap places after an upgrade, one is renamed. Columns are therefore lined up by header name, compared after removing spaces from the ends, so email and email are the same column and the order they appear in does not matter. Where a header name is missing, or the files have no header row, the columns are lined up by position instead.

Columns that do not line up are named in the report, in two lists: those found only in the old file, and those found only in the new one. Those columns take no part in the comparison, because there is nothing on the other side to compare them with. The practical effects are worth knowing in advance:

  • Adding a column to this month's export does not mark every row as changed. The new column is listed as being only in the new file, and the rows are judged on the columns the two files share.
  • A column that disappeared is not reported against any row either. It is a change to the file rather than to a record, and the report names it once, in the list of columns found only in the old file.
  • A renamed column looks like both at once: postcode appears under the old file's list and postal_code under the new file's, and the values in them are never compared. Rename one of them to match the other before comparing if you want changes in that column reported.

Reading those two lists first is the quickest check on whether you have the pair of files you think you have. When the only-in lists are long, the two files are usually different reports rather than two runs of one report. Merging CSV files with different columns or headers works through the same header drift from the other side of the problem, including how a renamed column gives itself away.

Comparing Only Some Columns

Plenty of exports carry a column that is rewritten every time they run: last_modified, exported_at, a batch or job number, a sequence generated fresh. Compare everything and every row comes back changed, which is true and useless. Name the columns you actually care about instead, and the rest are ignored when deciding whether a row changed.

It works the same way when the question is narrower than the file. To find out which prices moved between two price lists, compare the price column only: a row whose description was reworded stays unchanged, and the changed list is the one you came for. Two things to keep in mind. The columns you left out may well have changed — the report says nothing about them, and a row reported as unchanged is unchanged in the columns you named. And the files you download hold complete rows rather than only the compared columns, so a changed row arrives with all of its values.

Why Not VLOOKUP or a Spreadsheet?

For a few hundred rows in files that open without complaint, a spreadsheet is a reasonable answer and has one real advantage: you can see the rows. VLOOKUP, or XLOOKUP in newer versions, pulls last month's value in beside this month's, and for a one-off check of one column that is the end of it.

It stops being reasonable in three specific places:

  • Size. Both files have to fit on a sheet, so each is capped at 1,048,576 rows, and a lookup formula on every row of a file anywhere near that size is slow enough to become its own problem.
  • A lookup does not give you the four answers. It puts the old value next to the new one. Turning that into added, removed, changed and unchanged means wrapping it in IFERROR, running a second lookup in the other direction to catch the rows that disappeared, and repeating the whole arrangement for every column you want to check.
  • The values change as the file opens. Excel reads 00742 as the number 742, so the leading zeros are gone, and it keeps only the first 15 significant digits of a number, so a 16-digit account or transaction number arrives rounded and shown as something like 4.5E+15. A code such as MAR-1 is read as a date. That is fatal for a comparison, because keys are very often exactly those kinds of value: 00123 and 123 become one key, so a removed record and an added record appear as a single matched row, and two long IDs that agree in their first 15 digits become one row as well.

RowSlice reads the raw text of both files and compares text, never interpreting it, so 00123 and 123 stay two different keys and a long ID keeps every digit. Both files stream past 4 MB at a time instead of being loaded, so they can be far longer than a spreadsheet would open, and neither of them leaves your computer. What it will not do is show you the file: beyond the preview and the sample of changed rows, the answer arrives as counts and as CSV files you open elsewhere. If those files are going to somebody who works in Excel, write them out as .xlsx rather than opening the CSV in Excel, which would round the long IDs the comparison was careful to keep.

Last updated .

FAQ

Frequently Asked Questions

Which file goes first, and does the order matter?

Yes, the order decides the wording of the whole result. The first file is the older one — last month’s export, the state before a migration, the system of record — and the second is the newer one. Added and removed are named from the newer file’s point of view: a row whose key is in the new file and nowhere in the old one was added, and a row whose key is in the old file and never turns up in the new one was removed. Swap the two files over and the added rows become the removed ones. Nothing is judged either way; the tool has no idea which of the two files is right.

Can I match rows on more than one column?

Yes. Tick every column it takes to identify a record and their values are joined into one key, so store_id plus sku matches the row for one product in one store. Use the fewest columns that are genuinely unique. Every column added to the key is another value that can differ between two exports, and a key that differs is not reported as a changed row: it is a removed row and an added row, because the old key was never found and the new one was never seen before.

What happens if the same ID appears twice in one of the files?

The comparison becomes ambiguous — there is no way to tell which copy should be compared with which — so the tool counts the repeats and tells you rather than guessing. The first row with each key is the one that takes part; later rows with the same key are counted and otherwise left out. Treat any count above zero as a warning that the result describes the first row of each group only. To find out beforehand whether a column is unique, the CSV validator counts repeated values in a column you choose, and Remove Duplicates from CSV collapses them when the repeats really are the same record twice.

My two files do not have the same columns. Will it still work?

Yes. Columns are lined up by header name, compared after removing spaces at the start and end, so the two files can carry their columns in any order. Where a name is missing, or the files have no header row, the columns are lined up by position instead. Columns that exist in only one of the files are named in the report and left out of the comparison, because there is nothing on the other side to compare them with — which also means that adding a column to this month’s export does not turn every row into a changed row.

Can I ignore a column that changes on every export, such as last_modified?

Yes, and it is often the difference between a useful answer and a list of every row in the file. Choose the columns to compare and leave out the ones that are rewritten each time the export runs: last_modified, exported_at, a batch number, a sequence generated fresh. The choice only decides what counts as a change — the rows you download are complete rows from your files, not only the columns you compared.

Is this a line-by-line diff?

No, and the difference matters on a CSV. A text diff compares two files line by line, so re-sorting an export or inserting one row near the top makes everything below it look different. This tool matches rows on their key, so row order is irrelevant: a record that moved from line 40,000 to line 12 is unchanged, and the report says so. It also compares values whole rather than character by character — you get the value before and the value after for each column that changed, not which letters within it moved. Nothing is matched approximately either: CUST-0910 and CUST-910 are two different keys, so they come back as one removed row and one added row.

Does it give me one merged or reconciled file?

No. It writes the added, removed and changed rows to separate files and leaves both of your files exactly as they are. It never decides which version of a row should win, and never writes a file with the two sources woven together, because that decision belongs to whoever knows which system is authoritative. To stack two files into one, use Merge CSV Files. To put two files side by side and match them on a shared column — the join people do with VLOOKUP — use Merge Queries in Excel’s Power Query, a database such as DuckDB, or the merge function in Python’s pandas library.

Is there a limit on file size or the number of rows?

Not on size. Both files are read from your disk 4 MB at a time and no row is ever held in memory: the older file is read twice and the newer one once. What memory the run does use goes on the keys. For each different key in either file the tool keeps a 64-bit fingerprint of the key and a 64-bit fingerprint of the values being compared, rather than the row itself, so two different keys would have to produce the same fingerprint to be treated as one — about 1 in 3.7 billion for 100,000 different keys, and about 1 in 37 million for a million. The ceiling is about 8.3 million different keys across the two files: past it the comparison stops with a message naming the number it had reached, and saves no partial result rather than an answer it cannot stand behind. If you meet it, split both files by a column that groups the records — one file per store, region or month — and compare the pairs. You also need free disk space for the result files, within the storage your browser allows one site, which is about 10 GB in Firefox. Tested in current Chrome, Edge and Firefox on Windows; Safari and macOS are untested.

Are my two files uploaded anywhere?

No. Both files are read from your own disk by code running in your browser, and the results are written to your browser’s private storage on the same machine, so two customer exports or two payroll files never leave it. Once the page has loaded it works offline. There is no account and no copy on any server. Results stay in that private storage until you start another job, and anything left behind is removed after six hours the next time you use a tool.

More Tools

More CSV Tools

CSV Analyzer

Count the rows, list the columns and profile the values in a CSV too big to open.

CSV Viewer

Page through and search a CSV that is far too large for Excel, without uploading it.

Take a Sample from a CSV

Pull the first rows, every Nth row or a random slice out of a huge file for testing.

Sample CSV File Generator

Download realistic test CSV files from 10 rows up to 20 GB, with messy values on request.

Split Large CSV Files

Cut a CSV that Excel refuses to open into multiple files by rows, size or number of parts.

Split CSV by Column Value

One file for every store, region, client or status — straight from a huge export.

Filter CSV Rows

Keep only the rows you need — by value, text match or number range — from a file of any size.

Merge CSV Files

Combine multiple CSV files into one, lining up columns by name, even when the result is too big for Excel.

Remove Duplicates from CSV

Delete repeated rows from millions of records, comparing whole rows or chosen columns.

Convert CSV to Excel

Make a real .xlsx file without losing leading zeros, long IDs or turning codes into dates.

Convert CSV to JSON

Turn a CSV into a JSON array or NDJSON, with every value kept exactly as written.

Convert JSON to CSV

Flatten a JSON array or NDJSON export into a spreadsheet-ready CSV.

CSV Validator

Find the broken rows, bad quotes, wrong encoding and duplicate IDs before an import fails.

Convert CSV to UTF-8

Repair garbled characters like é by converting to UTF-8, and switch semicolons to commas.