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 local files and matching rules

Required in both files. No guessing, trimming, date conversion, or duplicate-key matching. Header and row order are ignored.

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.

This tool compares raw parsed strings using your explicit row key. Synthetic examples show seeded changes; they are not provider tests or proof of a successful real migration. Our editorial method

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.

Take it with you

CSV import acceptance worksheet

Download worksheet

Sources & verification

Product details and prices can change. Check the linked provider before buying.

  1. RFC 4180: Common Format and MIME Type for CSV Files (Informational) Accessed 14 Sep 2026

Sources link directly to providers. Product buttons may use separately labeled affiliate links. Read our disclosure.

Your decision at a glance

Compare the options

Full comparison

Documentation-based guidance. No tested ranking or performance score.

Email

Moosend

Consider it for
Email campaigns, segmentation, forms, and automation workflows. Use a small controlled trial to compare a named gap in your current welcome sequence before moving a live list.
Starting cost
30-day trial, no credit card required; paid quote depends on contacts and billing interval
Before you choose
The trial is time-limited. Documentation does not establish inbox placement, migration ease, or a lower bill for your list. Check the required plan and preserve opt-outs before importing.

Checked 20 Sep 2026 · Pricing source

View Moosend plans

Affiliate link: we may earn a commission on an eligible purchase. Link disclosure

Email

Kit

Consider it for
Use Kit Free for workshop broadcasts and tags. Consider Creator when buyers need timed sequences or visual automations; those features require a paid plan. Check the invoice for your subscriber count.
Starting cost
Free $0; Creator 1,000-subscriber example $33/mo billed yearly ($390/year) or $39/mo billed monthly (implied by $78/year savings), recaptured 2026-09-15
Before you choose
Subscriber count and billing interval change price. The paid workflow has not been tested.

Checked 15 Sep 2026 · Pricing source

View Kit plans

Direct provider link; no affiliate tracking added by this publication. Link disclosure

Automation

Make

Consider it for
Use Make to prepare weekly reminder drafts for review. Free includes 1,000 credits per month and a minimum scheduled interval of 15 minutes. Email delivery needs a connected service, which may cost extra.
Starting cost
Free plan includes 1,000 credits/month
Before you choose
Connected apps can cost extra. Free scheduled interval is at least 15 minutes; paid billing must be checked at checkout.

Checked 13 Sep 2026 · Pricing source

View Make plans

Affiliate link: we may earn a commission on an eligible purchase. Link disclosure

Email

MailerLite

Consider it for
Use groups for assigned membership and segments for rules when planning MailerLite recipients. The reviewed Free plan listed 250 subscribers, 2,500 emails per month and three automations; sending locks above the subscriber limit.
Starting cost
Free: up to 250 subscribers, 2,500 emails/month, 3 automations. Comfort $10.80/mo yearly-billed at 500 subscribers (listed $12/mo); Power $22.50/mo yearly-billed at 500 (listed $25/mo). Recaptured 2026-09-16.
Before you choose
USD; taxes may apply. Free sending locks above 250 subscribers. The September 16, 2026 trial displayed higher usage limits than the published Free plan; confirm the limits that apply after your trial ends.

Checked 16 Sep 2026 · Pricing source

View MailerLite plans

Affiliate link: we may earn a commission on an eligible purchase. Link disclosure

Domains

Namecheap

Consider it for
Compare Namecheap for domain registration or Stellar shared hosting. Treat the domain, hosting trial, first paid term and later renewals as separate costs; confirm the full invoice before buying.
Starting cost
.com first-year sale $11.28 (renews $18.48). Stellar $0 for 30 days then $2.28/mo displayed (1st year); 1-month $5.88; 1-year $55.88; 2-year $102.88. Recaptured 2026-09-15 from https://www.namecheap.com/domains/registration/gtld/com/ and https://www.namecheap.com/hosting/shared/.
Before you choose
Promotional and renewal prices differ. We have not registered a domain or hosted a site with Namecheap.

Checked 15 Sep 2026 · Pricing source

View Namecheap plans

Direct provider link; no affiliate tracking added by this publication. Link disclosure

Email

beehiiv

Consider it for
Consider beehiiv Launch for newsletter broadcasts within its documented free allowance of up to 2,500 subscribers. Compare paid features and the complete invoice for your list size before upgrading.
Starting cost
Launch $0 at the 1,000-subscriber selector (page also lists Launch up to 2,500 subscribers). JSON-LD Scale $49/mo, Max $109/mo. Annual display: Scale $43/mo ($517/year); Max $96/mo ($1,151/year). Recaptured 2026-09-15 from https://www.beehiiv.com/pricing.
Before you choose
Launch and paid Scale or Max have different limits. We observed a test-send acknowledgement on September 15, 2026; inbox receipt and subscriber campaign delivery remain unverified.

Checked 15 Sep 2026 · Pricing source

View beehiiv plans

Affiliate link: we may earn a commission on an eligible purchase. Link disclosure

Automation

Pabbly Connect

Consider it for
An alternative to Make for connecting apps. Free includes 100 tasks per month; Standard costs $194 upfront on annual billing. Pabbly tasks and Make credits count usage differently.
Starting cost
Free $0 (100 tasks/month). Standard $19/mo or $194/year (10,000 tasks). Unlimited $79/mo or $69/mo billed yearly. Recaptured 2026-09-15 from https://www.pabbly.com/connect/?currency=usd.
Before you choose
Tasks are not Make credits. Connected apps can cost extra. No Pabbly workflow was tested here.

Checked 15 Sep 2026 · Pricing source

View Pabbly Connect plans

Direct provider link; no affiliate tracking added by this publication. Link disclosure