Local CSV comparison
What changed in the exported copy?
Choose both files and an exact row-key column. No values or filenames are uploaded or stored. Reload or Clear files removes the current inputs.
Choose both UTF-8 files, enter the row key, and compare. JavaScript is required for local processing.
Limits per file: 1,048,576 bytes (1 MiB), 10,000 data rows, 100 columns, 200,000 cells. At most 500 detailed differences and 50 ambiguity issues are returned; summaries retain full counts. Use smaller files for complete detail. UTF-8 only; malformed quotes and cells without a header are rejected.
Original synthetic examples · 1.0.0
Try known changes before your own files
Download a pair, choose each file above, enter its listed key, then compare. Expected outcomes were authored independently. These files are fictional, not vendor exports.
Download machine-readable expected results
zeros · Non-key identifiers retain leading zeros; no number conversion.
Key: id. Delimiters: comma in both files.
Expected outcome: compared.
{
"status": "compared",
"summary": {
"beforeRows": 1,
"afterRows": 1,
"addedRows": 0,
"removedRows": 0,
"changedRows": 1,
"changedValues": 1,
"addedHeaders": 0,
"removedHeaders": 0
},
"differences": [
{
"type": "changed-value",
"key": "row1",
"header": "account",
"before": {
"present": true,
"value": "0012"
},
"after": {
"present": true,
"value": "12"
}
}
]
}dates · Ambiguous dates compared as raw strings without locale inference.
Key: id. Delimiters: comma in both files.
Expected outcome: compared.
{
"status": "compared",
"summary": {
"beforeRows": 1,
"afterRows": 1,
"addedRows": 0,
"removedRows": 0,
"changedRows": 1,
"changedValues": 1,
"addedHeaders": 0,
"removedHeaders": 0
},
"differences": [
{
"type": "changed-value",
"key": "1",
"header": "date",
"before": {
"present": true,
"value": "03/04/2026"
},
"after": {
"present": true,
"value": "2026-03-04"
}
}
]
}rows · Added and missing rows are reported using the selected exact key.
Key: id. Delimiters: comma in both files.
Expected outcome: compared.
{
"status": "compared",
"summary": {
"beforeRows": 2,
"afterRows": 2,
"addedRows": 1,
"removedRows": 1,
"changedRows": 0,
"changedValues": 0,
"addedHeaders": 0,
"removedHeaders": 0
},
"differences": [
{
"type": "removed-row",
"key": "2",
"row": [
{
"header": "id",
"value": {
"present": true,
"value": "2"
}
},
{
"header": "note",
"value": {
"present": true,
"value": "gone"
}
}
]
},
{
"type": "added-row",
"key": "3",
"row": [
{
"header": "id",
"value": {
"present": true,
"value": "3"
}
},
{
"header": "note",
"value": {
"present": true,
"value": "new"
}
}
]
}
]
}duplicates · Duplicate row keys make the entire comparison unresolved.
Key: id. Delimiters: comma in both files.
Expected outcome: unresolved.
{
"status": "unresolved",
"issueCodes": [
"DUPLICATE_KEY"
]
}empty-missing · An absent trailing cell differs from an explicitly empty cell.
Key: id. Delimiters: comma in both files.
Expected outcome: compared.
{
"status": "compared",
"summary": {
"beforeRows": 2,
"afterRows": 2,
"addedRows": 0,
"removedRows": 0,
"changedRows": 1,
"changedValues": 1,
"addedHeaders": 0,
"removedHeaders": 0
},
"differences": [
{
"type": "changed-value",
"key": "1",
"header": "note",
"before": {
"present": false
},
"after": {
"present": true,
"value": ""
}
}
]
}unchanged-quotes · Quoted delimiters, escaped quotes and embedded newlines remain equal despite row and header reorder.
Key: id. Delimiters: comma in both files.
Expected outcome: compared.
{
"status": "compared",
"summary": {
"beforeRows": 2,
"afterRows": 2,
"addedRows": 0,
"removedRows": 0,
"changedRows": 0,
"changedValues": 0,
"addedHeaders": 0,
"removedHeaders": 0
},
"differences": []
}headers · Exact header renames are one removed and one added header, with missing-cell differences.
Key: id. Delimiters: comma in both files.
Expected outcome: compared.
{
"status": "compared",
"summary": {
"beforeRows": 1,
"afterRows": 1,
"addedRows": 0,
"removedRows": 0,
"changedRows": 1,
"changedValues": 2,
"addedHeaders": 1,
"removedHeaders": 1
},
"differences": [
{
"type": "changed-value",
"key": "1",
"header": "old",
"before": {
"present": true,
"value": "x"
},
"after": {
"present": false
}
},
{
"type": "changed-value",
"key": "1",
"header": "new",
"before": {
"present": false
},
"after": {
"present": true,
"value": "x"
}
}
]
}key-change · Changed key strings cannot be inferred to identify the same row.
Key: id. Delimiters: comma in both files.
Expected outcome: compared.
{
"status": "compared",
"summary": {
"beforeRows": 1,
"afterRows": 1,
"addedRows": 1,
"removedRows": 1,
"changedRows": 0,
"changedValues": 0,
"addedHeaders": 0,
"removedHeaders": 0
},
"differences": [
{
"type": "removed-row",
"key": "0012",
"row": [
{
"header": "id",
"value": {
"present": true,
"value": "0012"
}
},
{
"header": "note",
"value": {
"present": true,
"value": "x"
}
}
]
},
{
"type": "added-row",
"key": "12",
"row": [
{
"header": "id",
"value": {
"present": true,
"value": "12"
}
},
{
"header": "note",
"value": {
"present": true,
"value": "x"
}
}
]
}
]
}Review the CSV import method, then record the result in the acceptance worksheet.
Make a small round trip first
Keep an untouched original. Import a small representative copy into the destination, export it again, and choose those two CSV files below. Enter a column name that uniquely identifies each row in both files.
A key such as a stable record ID is usually more useful than a name. If the chosen key itself changes, this tool reports a removed row and an added row; it cannot infer that they represent the same person. Resolve duplicate or missing keys before comparing.
Read differences without guessing repairs
Header names and keys match exactly, including whitespace and case. Row order and header order do not count as changes. Values remain strings: 0012 differs from 12, and 03/04/2026 is not interpreted as a date.
An explicit empty string is different from an absent cell. Missing or duplicate headers and empty, missing, or duplicate keys prevent comparison. A short row is retained as missing cells; an extra cell without a header is rejected.
Choose comma, semicolon, or tab separately for each file. Files must be UTF-8, optionally with a BOM. Quoted delimiters, escaped quotes, and quoted newlines are supported. This is a documented local dialect informed by RFC 4180, not a claim that every CSV dialect is supported.
Turn findings into an acceptance record
Check the seeded examples first. Then examine your own changed values and unexpected row or column changes. Download the JSON difference report if you need a local record; it preserves missing versus empty values and does not rewrite your CSV.
Use the existing CSV acceptance worksheet to record what you verified, unresolved differences, and the person responsible for the final import. A completed comparison is one check, not proof that automations, consent, relationships, or dates behave correctly after migration.
Sources & verification
Product details and prices can change. Check the linked provider before buying.
- RFC 4180: Common Format and MIME Type for CSV Files (Informational) Accessed 2026-09-14
Sources link directly to providers. Product buttons may use separately labeled affiliate links. Read our disclosure.
