CSV Diff & Reconciliation – Compare Two CSV Exports by Key
Pricing
$1.80 / 1,000 parity exception founds
CSV Diff & Reconciliation – Compare Two CSV Exports by Key
Compare two CSV exports by key and get one row per difference: mismatched fields, rows missing on either side, duplicate and blank keys. Explicit column mapping, composite keys, every row accounted for. Matches are free. No API keys.
Pricing
$1.80 / 1,000 parity exception founds
Rating
0.0
(0)
Developer
Kestrelwick Studios
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Paste two CSV exports of the same records (say, your shop's orders and your accounting system's orders) and get one row per problem: values that don't match, records missing on either side, duplicate keys and blank keys. You tell us which columns hold the key and which columns should agree, and we account for every single row on both sides, so nothing slips through silently.
Values are compared as exact strings. We don't guess at numbers or dates, round anything or "fix" your data: 10.00 vs 10 is reported, and raw values are always kept in the output. Everything runs inside the run, with no API keys, proxies or outside services.
Built and maintained by Kestrelwick Studios.
Who it's for
- Finance and ops teams reconciling orders, invoices or payouts between a store, a payment provider and the books.
- Data and CRM teams checking a migration or sync: did every record arrive, and did the fields survive?
- E-commerce sellers comparing a supplier feed with their catalog (SKU, price, stock).
- Developers and analysts who need a repeatable parity check they can call from the API, Make, Zapier or n8n.
What we return
One dataset row per finding:
type | Meaning |
|---|---|
MISMATCH | The key exists once on each side, but at least one compared column differs. changedFields lists each column pair with both raw values. |
LEFT_ONLY / RIGHT_ONLY | The key exists on one side only. |
DUPLICATE_KEY | The key appears more than once on either side. We quarantine every row with that key (on both sides) instead of picking a winner; keyGroupCounts shows how many on each side. |
MISSING_KEY | A row has a blank key value. |
MATCH | An identical pair. Only written if you turn on Include matching pairs, and always free. |
Every row also carries the normalized key, a left and right reference (record number, physical line, the raw key and compared values) and a stable id you can use to dedupe downstream.
A run summary is saved as SUMMARY in the run's key-value store: overall status (EQUAL, EXCEPTIONS or EMPTY), counts per finding type, and per-side row accounting where parsedRows always equals missing + duplicate + one-sided + matched + mismatched rows. complete: true means every finding was saved.
Input
- Left CSV and Right CSV: paste each export, header row included (up to 2 MiB and 20,000 rows per side, 64 columns).
- Key columns: pairs of header names, for example
[{"left": "order_id", "right": "Order ID"}]. Add up to 8 pairs for a composite key. - Columns to compare: pairs of header names whose values should agree, for example
[{"left": "total", "right": "Amount"}]. Columns you don't list are ignored. - Delimiter: comma, semicolon or tab (the same for both files).
- Key matching and Value comparison:
exact(default),trim(ignore surrounding spaces) ortrim_ascii_lower(also ignore A–Z case). - Include matching pairs: also write a free
MATCHrow for every identical pair.
{"leftCsv": "order_id,total,status\nA-1001,49.00,paid\nA-1003,120.00,refunded\n","rightCsv": "Order ID,Amount,Payment Status\nA-1001,49.00,paid\nA-1003,120.00,paid\n","keyPairs": [{ "left": "order_id", "right": "Order ID" }],"comparePairs": [{ "left": "total", "right": "Amount" }, { "left": "status", "right": "Payment Status" }]}
Output example
{"type": "MISMATCH","key": ["A-1005"],"left": { "record": 5, "lineEnd": 6, "keyValues": { "order_id": "A-1005" },"compareValues": { "email": "eli@example.com", "total": "64.20", "status": "paid" } },"right": { "record": 6, "lineEnd": 7, "keyValues": { "Order ID": "A-1005" },"compareValues": { "Customer Email": "eli@example.com", "Amount": "64.02", "Payment Status": "paid" } },"changedFields": [{ "leftHeader": "total", "rightHeader": "Amount", "leftValue": "64.20", "rightValue": "64.02" }],"id": "42ad32f2e1cd085226076a7b755115e517206b11abfb80c8be656890ad2f8fc6"}
Export the findings as CSV, Excel, JSON or XML, or read them from the Apify API.
Pricing
Pay per result: $1.80 per 1,000 exception rows (mismatches, one-sided rows, duplicate-key and missing-key rows). Matching rows are free, there's no start fee, and a clean audit with no exceptions costs nothing in event fees. Platform usage is included. Set a maximum charge per run to cap spend: if we reach it, we stop, mark the summary complete: false, and you're never charged past your limit.
Strict by design
- Header names are matched exactly and are case-sensitive.
- All cells stay strings: no number, date or null interpretation.
001≠1,NULLis just text. - We accept quoted fields, embedded newlines, CRLF/LF line endings and a leading BOM. We reject malformed CSV (stray quotes, ragged rows, duplicate or missing headers) with a clear error instead of guessing, and we never truncate oversized inputs.
- Findings come out in a deterministic order with deterministic IDs, so the same input always gives the same result.
Tips
- Compare a few columns that matter (amount, status, quantity) rather than every column, so the findings stay readable.
- If one system pads or upper-cases IDs, set Key matching to
trimortrim_ascii_lower. Raw values are still shown. - Start a fresh run for each audit; don't append to an old dataset.
- If you open the results in a spreadsheet, keep its formula protection on: we return your values unchanged, including any that look like formulas.
FAQ
Can it read files or URLs? Not in this version: paste the CSV text into the input (or send it through the API). That keeps runs fast and your data inside the run.
Why is 10.00 vs 10 a mismatch? We compare exact text on purpose, so formatting drift between systems is caught rather than hidden.
What happens with duplicate keys? Every row sharing that key is reported as DUPLICATE_KEY on both sides; we don't pair them up, because any pairing would be a guess.
How fast is it? Two 20,000-row exports are audited in a couple of seconds.
Support: open an issue on the actor's Issues tab and we'll respond.