Nuxy Automation

CSV Contact Cleaner

Before you import a contact list into a CRM, an email tool or a new database, run it through this. It fixes what can be fixed safely, merges duplicates, and puts everything doubtful in a separate file for a person to check. Nothing is guessed, and every change is counted in a report.

node bin/clean-csv.js contacts.csv --map "email=Email,phone=Phone,name=Full Name,date=Signed up" --out out
# contacts.csv: 11 read, 6 clean (1 duplicates merged), 4 to check -> out/

The input file is never changed. You get three files:

File What’s in it
clean.csv Rows ready to import. Fields are normalised in place, first_name and last_name are added, and duplicates are merged (with merged_lines showing which rows were combined).
needs-review.csv Rows a person must look at, each with a reasons column, exactly as they were typed.
report.md What happened, in counts a client can read.

Before and after (from fixtures/contacts-messy.csv)

Before After
JORDAN EXAMPLE, Jordan.Example@Example.com , (555) 010-4477, 10/27/2026 Jordan Example, jordan.example@example.com, +15550104477, 2026-10-27
A second Jordan row from 2026-09-02 with a note Merged into the row above: the newest signup wins and the blank Notes cell is filled from the older row
Chen, Wei (last name first) Wei Chen, first Wei, last Chen
priya.patel@gmial.com priya.patel@gmail.com (only unambiguous provider typos)
27.10.2026, Oct 3, 2026, 9/15/26 2026-10-27, 2026-10-03, 2026-09-15
+44 20 7946 0958, 0049 30 1234567 +442079460958, +49301234567
not-an-email Sent for review: “invalid email”
02/30/2026 Sent for review: “impossible date”
A row with no email or phone Sent for review: “no email or phone to contact”
A stray comma shifting the columns Sent for review: “1 value(s) past the last column”

Options

Duplicates are rows with the same email, or the same phone when there’s no email. The newest by the mapped date wins, and its blank cells are filled from the others.

Tested

npm test   # the CSV parser (quotes, newlines in fields, CRLF, BOM), each normaliser, the sample end to end, the CLI

Zero dependencies; it needs Node.js 20 or later. The CSV parser follows RFC 4180, so the commas, quotes and line breaks that spreadsheets put inside fields are handled.