👤CSV→VCF

Remove Duplicate Contacts From a VCF File

Drop one .vcf, pick strict or loose matching, and download a file with the extra copies taken out. This VCF duplicate remover keeps the first card in each group as original bytes. Free, in your browser, nothing uploaded.

👤
Written by Casey Marlin · Last updated
This update: dedupe covered by scripts/test-dedupe.mjs: strict finds one group for two cards with the same name and phone, loose catches the same email under a different name, unrelated cards are untouched and the kept card's bytes are unchanged
VCF duplicate remover: contacts.vcf checked against a name plus phone digits plus emails key in strict mode, or a shared phone or email in loose mode; first copy kept as original bytes including PHOTO

Drop a VCF / vCard file here

One .vcf file — extra copies dropped on your device. A second file replaces the first. Nothing is uploaded.

100% in your browser — your contacts never leave your device

How duplicates are matched — the exact key

This page does not guess who is the same person. In strict mode it builds a key from three pieces of the card, using the same parser as the rest of this site, and it only uses that key to decide whether two cards belong together. Loose mode uses a different rule, described in the next section. The key is not written into the download. It is identification only.

The display name is lower-cased and trimmed. It is the same display name the rest of this site uses to label a card: FN if present, otherwise the N parts, otherwise ORG, otherwise the first email, otherwise the first phone. The parser fallback “Unnamed contact” is not treated as a real name; a card that would only have that fallback contributes an empty name to the key.

Phone numbers are reduced to digits and sorted. +1 (555) 010-1 and 15550101 become the same digit string. Formatting, spaces, dashes, parentheses and a leading plus are ignored. The order of TEL lines on the card does not matter, because the digits are sorted before they go into the key. Two cards whose phone lists differ after that reduction — one mobile versus that mobile plus a work line — are different people under the strict rule.

Emails are lower-cased, trimmed and sorted. Bob@Example.com and bob@example.com are the same email. Extra spaces around the address are stripped. The three pieces are joined as name|phones|emails. A card with none of the three — no usable name, no phone digits, no emails — produces a null key and is never a duplicate. Two photo-only remnants sitting next to each other are not grouped.

There is no fuzzy matching. “J. Smith” and “John Smith” differ. A nickname and a legal name differ. We do not soundex, we do not strip middle initials, and we do not treat a shortened FN as the long form. If you need that kind of cleanup, convert the file with the VCF to CSV converter and edit it in a spreadsheet, then convert back with the CSV to VCF converter if you still need a vCard. That round-trip drops PHOTO; this page exists so exact copies can be dropped without that loss.

Strict vs loose

The radio labelled Strict — same name, phone digits and email is the default. Strict requires all three pieces of the key to match. The first card in the file with a given key is kept; later cards with the same key are listed as removed. Cards whose key is null are never grouped. That is the boring, safe case: you exported the same account twice, or someone mailed you a vCard you already had from a previous dump.

The radio labelled Loose — same phone OR same email is a different rule. Two cards are linked when they share any one phone-digits string, or any one lower-cased email. Links are transitive: if A shares a phone with B, and B shares an email with C, A, B and C become one group of three. The card with the lowest position in the file is kept; the rest of the group are listed as removed. A card with no phone and no email is never linked in loose mode, even if another card has the same display name and nothing else. Name-only cards are invisible to the loose rule.

Loose is useful when the same person was saved twice under different names — Bob with EMAIL:Bob@Example.com and Robert Smith with EMAIL:bob@example.com. Strict sees two different names and leaves both. Loose sees the shared email and groups them. The same happens for a mobile written as +1 (555) 010-1 on one card and as digits on another, even when the FN lines disagree.

Loose can also merge two different people. A shared landline, a family email, a company switchboard, a couple who both listed the house number — any of those will link the cards, and transitivity can pull in a third person who only shares an email with the second. That is why the group list is on the page. Each group shows the Kept card and every Removed card, with the display name, the first phone and first email when the card has them, and the 1-based position in the file. The list shows the first 25 groups; a line under it counts any beyond that. Read that list before you download. If a group looks wrong, the cleaned file is not what you want; switch back to strict, or take the file to a spreadsheet.

The summary line updates as you switch radios: N contacts found, how many duplicate groups, how many to remove, how many kept. Switching does not rewrite any card; it only changes which indexes are kept and which are removed. When there are no groups under the current rule, the page says so, and the cleaned download is every complete card in original order.

What “kept” means — first occurrence, bytes untouched

Within a group the card with the lowest position in the file is kept. Card #1 is the first BEGIN:VCARD block the splitter found, card #2 the next, and so on. “First occurrence” means first in that order, not first alphabetically and not the card with more fields. If the older, thinner copy happens to sit earlier in the file, that is the copy that survives. The tool does not pick the “best” card.

Kept cards are the original BEGIN:VCARD END:VCARD text. They are joined with CRLF between them, plus a trailing CRLF. Nothing is rewritten. PHOTO stays, including PHOTO;ENCODING=b and folded base64. X- fields stay. Line folding stays. Each card keeps its own VERSION. A 2.1 quoted-printable name stays quoted-printable. A 4.0 tel: URI stays a tel: URI. Mixed versions in one file are left mixed; importers read VERSION per card.

The tool does not merge fields from removed cards into the kept card. If the kept copy has a mobile and the removed copy has a work email the kept copy lacked, that work email is not copied across. It goes to the removed download, if you take it. A parse-and-rewrite merger would flatten those fields into one new card and drop everything it did not have a column for. This page refuses that trade.

Text that sat outside a card in the source is not carried into either download. A byte-order mark, a comment line, a card cut off at the end of the file before its END:VCARD — those are ignored the same way the splitter on this site ignores them. Only complete BEGIN…END blocks are in play. Line endings inside a kept card are whatever the source file used. The file is read as UTF-8 text, so a UTF-8 or ASCII .vcf comes out byte for byte; a legacy single-byte encoding such as Latin-1 would have its non-ASCII bytes turned into replacement characters.

Removed cards can be downloaded as a separate file, named from the source with -removed.vcf. That file is also original blocks joined with CRLF. It is there so you can check what was dropped, or import it later if you change your mind. The cleaned file is named from the source with -deduped.vcf, or contacts-deduped.vcf if the source had no usable name. If there are no duplicate groups under the current rule, the cleaned file is every complete card, still byte-preserved, and the removed button is not shown.

Why phones import duplicates — iCloud, Google and the SIM

A phone can show the same person from several accounts at once. iCloud, a Google account, the SIM — each is a separate store, and an old export sitting in Files becomes another the moment you import it. The address book on the device can show those copies side by side rather than collapsing them. That is not a bug in the .vcf. It is how the device paints several stores into one list.

Importing a .vcf adds cards. It does not replace the copy that is already there. Import the same export twice and you get two of everyone who was in it. Import an iCloud dump on top of a Google sync and you get both. A SIM that still holds an older subset of the same people adds a third row for each of them. The import step itself does not apply a rule like this page's key; it appends, and any duplicate cleanup an account offers is a separate step afterwards.

This page does not talk to iCloud, Google or the SIM. It does not delete anything on the device. It only reads a file you drop and writes a smaller file. The usual path that produces a pile of copies is: export from one account, export from another, import both into a third. Each import adds. There is no “replace my whole address book with this file” button on most phones. Cleaning the file does not clean the phone until you import into an empty book, or delete the old copies first.

The practical sequence is: export once, clean here, import once. If you already have several exports, merge the VCF files first so you have one stream, then drop that stream here. If you are not sure what is inside a file, open it in the VCF viewer and read the names before you remove anything.

This is a general behaviour of imports, not a statistic about any one product. Phones add on import. They do not replace. Plan the import as a replace-by-hand: back up, clean the backup, clear or archive the on-device list if that is the goal, then bring the cleaned file in once.

After cleaning — importing the file again

The download is a vCard file. Import it the same way you would import any other .vcf. The iPhone import guide covers AirDrop and iCloud.com. The Android import guide covers opening the file and Google Contacts' Import. iCloud.com accepts a vCard upload; the iCloud contacts guide walks that. If you want to look at the cleaned file before you import it, open it in the VCF viewer.

Importing the cleaned file on top of the existing address book still leaves the old duplicates on the device. The new file does not overwrite Jane Doe #1 just because it also contains a Jane Doe. Delete or back up the existing contacts first if the goal is a clean list. Back up by exporting, then clean that export here, then — only if you are sure — remove the on-device copies and import the cleaned file once.

The cleaned file does not include text that sat outside a card, and it does not include the removed cards unless you download those separately. Keep the removed file if you are unsure; it is the original blocks, not a rewritten summary. You can drop it on this page again, or open it, or import it later. Nothing in the cleaned file points back at the cards that were dropped.

If you still need fuzzy cleanup — nicknames, “J. Smith” versus “John Smith”, two people who share a household number that loose mode would glue together — this is the wrong tool. Convert to CSV, edit in a spreadsheet the way you actually recognize people, convert back. You will lose PHOTO on that round-trip; that is the trade, and it is why this remover exists as a separate page instead of being folded into the spreadsheet tools.

Cards in the cleaned file appear in source order, with the removed indexes pulled out. Appending is not this page's job — that is the merger. Splitting the cleaned file into one .vcf per contact is the job of the VCF splitter. Use this page when the file already has extra copies and you want the extras gone without rewriting anyone you keep.

VCF duplicate remover — FAQ

  • How do I remove duplicate contacts from a VCF file?

    Drop one .vcf onto the box above, or pick it with Choose .vcf file. A second file replaces the first. The file is split into original BEGIN:VCARD blocks. Choose Strict (same name, phone digits and email) or Loose (same phone OR same email). The summary shows how many contacts, how many duplicate groups, how many to remove and how many kept. Download cleaned .vcf writes the kept cards; Download removed.vcf, when it appears, writes the ones that were dropped.

  • What counts as a duplicate in strict mode?

    A later card is grouped with an earlier one when its display name (lower-cased and trimmed), its phone numbers reduced to digits and sorted, and its emails (lower-cased and sorted) all match. The first card with that key is kept. A card with no name, no phones and no emails is never a duplicate. “J. Smith” and “John Smith” are not a match.

  • What does loose mode match?

    Two cards are linked when they share any phone-digits string or any lower-cased email. Links are transitive: A sharing a phone with B and B sharing an email with C becomes one group of three. Cards with no phone and no email are never linked. The earliest card in the file in each group is kept. Loose can group two different people who share a landline or a family email — check the group list before you download.

  • Which copy is kept when duplicates are found?

    The card with the lowest position in the file. Card #1 is the first complete BEGIN:VCARD block, then #2, and so on. Fields from removed cards are not copied into the kept card.

  • Are the kept contacts changed in any way?

    No. Each kept card is the original BEGIN:VCARD … END:VCARD text, joined with CRLF plus a trailing CRLF. PHOTO, X- fields, folding and VERSION stay as they were. The parser is used to build the duplicate key and the on-page group list. Output is never re-serialized. Text outside a card in the source is not carried into the download.

  • Why does my phone show duplicate contacts after an import?

    A phone can show the same person from several accounts — iCloud, a Google account, the SIM — and each import of an old export adds cards rather than replacing the ones already there. This page does not talk to the phone. Export once, clean the file here, then import once. Importing the cleaned file on top of the existing address book still leaves the old copies on the device.

  • Is the file uploaded to a server?

    No. The file is read with the browser File API and processed in JavaScript on your device. There is no upload endpoint. After the page has loaded you can disconnect from the network and the remover still works. The same rule applies to every tool on this site.

Kept cards are original BEGIN:VCARD blocks (RFC 2426, RFC 6350 and vCard 2.1, including PHOTO and unknown properties). The duplicate key uses the same parser as the rest of this site for identification only — output is never re-serialized; the dedupe path is exercised by scripts/test-dedupe.mjs. Last checked: August 26, 2026. About this site