🧹 CSV Cleaner & Contact List Formatter

Drop a messy contact list and get it back deduped, with every valid phone in E.164 and the rest counted and marked for you, one Name column split into First and Last, and the junk addresses pulled out into their own file. Your list is read inside this tab and is never uploaded.

📄
Drop a CSV here
or click to choose. TSV and semicolon files work too, the separator is detected.

Your file is never sent anywhere. The only requests this page makes are for its own code, anonymous counters that record a page view, a file being opened and a clean being run with nothing about the file attached to them, and the optional disposable domain block list if you switch that one filter on.

1Your file

2Which column is what

Detected from your headers. Fix anything it got wrong, and set unused ones to none.

3Phone numbers

What phone validation here can and cannot tell you. Numbers are checked against libphonenumber's prefix and length metadata, which is the same data Google's own libraries use. That catches wrong lengths, dead area codes and trunk prefixes left in place. It cannot tell you whether a number is disconnected, ported, or reachable, because that needs a live carrier lookup. Two more honest limits:
  • In the US and Canada the metadata does not separate mobile from landline, so the line type column reads FIXED_LINE_OR_MOBILE there. That is the data being truthful, not a bug.
  • The country column is a best guess. +44 7911 123456 comes back as Guernsey, not the UK, because they share the +44 calling code. Rows on a shared code get a yes in phone_cc_shared.

4Email addresses

This is a syntax and reputation pass, not verification. A browser cannot open an SMTP socket or do an MX lookup, so nothing here proves an address exists. A perfectly formed address at a real domain can still bounce, which is exactly what happens with registry scraped lists. Use this to cut the obvious junk before you pay a verifier, not instead of one.

5Names, spacing and dates

This is asked rather than guessed on purpose. 01/02/2024 is a valid date in both orders, and letting the browser decide silently turns 1 February into 2 January.

6Duplicates

The survivor rule, so the same file always gives the same result. Rows that share an email or a phone are grouped together, and within a group the row with the most filled fields wins, ties broken by whichever appeared first in the file. Every empty field on the winner is then filled from the other rows in file order, and tags are combined. The full list of what was merged into what goes into duplicates.csv.

7Output

Rows per file, for daily sending caps. 0 means do not split.

Result

Cleaned, first rows
Rejected, first rows
Merged duplicates, first rows
🎬 Plus PDF signing, batch watermarking, video compression & 250+ more free toolsOpen Castwright

Why this one runs in your browser

The real objection to every free CSV cleaner is that you are handing a client's lead list, with names, emails and phone numbers on it, to a stranger's server. There is no upload step here to hand it to. The file is read by your own browser, every pass runs on your own machine, and the ZIP is built locally before it downloads. Close the tab and it is gone. That matters more than any feature comparison when the list belongs to someone who trusted you with it.

The six passes it makes

Whitespace and unicode first, so a name with a non breaking space stops looking different from the same name without one. Then names: one Name column split into First and Last, with the particles in "Juan de la Cruz" kept on the surname side, and shouty ALL CAPS entries turned back into normal case. Then phones, parsed properly rather than by stripping digits and hoping. Then emails, checked for syntax and screened against role prefixes, typo domains and optionally a disposable list. Then any date column you pick, rewritten as YYYY-MM-DD in the order you tell it. Then duplicates, matched on email and on the E.164 form of the phone so that 0300 1234567 and +923001234567 are recognised as one person.

Why the phone pass is the part that actually saves you

Most CRMs and every SMS platform want E.164, the plus and country code form. The usual homemade fix is to strip everything that is not a digit and glue a country code on the front. That quietly breaks half of the world, because the UK, Germany, France, Australia and many others write national numbers with a leading zero that has to come off before the country code goes on. The result is a number that looks right, imports cleanly, and never delivers. This tool uses libphonenumber's real metadata instead, so a number that cannot be valid is told to you before you import it rather than after your first failed send.

What it deliberately does not claim

It does not verify that an email exists, because no browser can. It does not tell you whether a phone is a live mobile, because that needs a carrier lookup you have to pay for. It does not promise that any particular CRM will accept the file, and it does not pretend that GoHighLevel silently swallows bad rows, because it does not: GHL shows import errors and lets you map columns by hand. What this saves you is the part that is genuinely tedious, which is reformatting thousands of phone numbers correctly and working out which of your rows are the same person twice.

Sizes and speed

Parsing is streamed off the main thread where your browser allows it, so the tab stays responsive. A list of a few thousand rows finishes almost instantly. Around fifty to a hundred thousand rows expect a few seconds, and the progress bar tells you where it is. Past that you are pushing what a browser tab can hold in memory, so split the file first.