Best Practices for Generating vCard (.vcf) Files — A Complete Developer Guide
The vCard format is deceptively simple. It’s just a text file with a handful of fields… until it isn’t.
Maybe you’ve experienced this already: your app generates a .vcf file that looks valid — it even works in one contact manager — but then Gmail rejects it, or iOS silently drops parts of it, or Outlook decides to strip everything except the name.
This guide walks developers through best practices for generating vCard files that work consistently across platforms, using modern conventions and avoiding the subtle traps that cause import failures. Whether you’re exporting contact data from a CRM, building a sync feature, or generating downloadable .vcf cards for your users, these patterns will save you hours of debugging.
- Choose the Right vCard Version (Hint: It’s Probably 3.0)
Before writing a single field, you need to decide which vCard version to generate. The top contenders:
vCard 2.1
Extremely old
Used primarily by legacy systems and some older feature phones
Supports non-UTF-8 encodings
Highly inconsistent field parameter rules
Only recommended if your users are on legacy corporate systems or old devices
vCard 3.0
The de facto universal standard
Supported by: Google Contacts, iCloud, iOS, macOS, Android, Outlook, CRMs
UTF-8 compatible
Stable, predictable import behavior
Recommended for most applications
vCard 4.0
The current official IETF standard
Better structured value types
More predictable address and date formats
Better support for multi-value fields
Weak support in Microsoft products and some Android contact managers
Best practice recommendation
Unless your user base requires otherwise:
VERSION:3.0
vCard 3.0 strikes the safest balance between capability, practicality, and interoperability.
- Always Include Both FN and N Fields — Even If They’re Redundant
Many developers generate only FN: (full name). Some only generate N: (structured components). Both choices lead to platform quirks.
Why both are needed
Google Contacts uses FN as the display name
iOS/macOS primarily rely on N for component parsing
Outlook uses both in different contexts
CRMs often split fields based on N
Best practice structure FN:Jane Doe N:Doe;Jane;;;
Even if you don’t have all the name components (prefix, suffix), include the correct number of semicolons to maintain structure.
- Normalize Character Encoding (UTF-8 Everything)
Half of all vCard import problems come from encoding inconsistencies. The fix:
Always output UTF-8
Do not declare a charset unless required
Avoid mixing line endings from different OS environments
Escape special characters properly (,, ;, \n)
Common failure scenario
Developers generate vCards containing:
Accented characters
Emojis
Non-ASCII punctuation
Smart quotes from user-submitted forms
…and then clients misinterpret the file as ISO-8859-1 or Windows-1252.
Best practice
Make UTF-8 your default output:
Content-Type: text/vcard; charset=utf-8
- Properly Format Phone Numbers, Emails, and URLs With Type Parameters
Contacts without type metadata often import incorrectly or get collapsed into the wrong buckets.
The wrong way: TEL:5551234567 EMAIL:[email protected]
The right way: TEL;TYPE=cell:+1-555-123-4567 EMAIL;TYPE=work:[email protected] URL;TYPE=homepage:https://www.example.com
Why this matters
iOS decides where to display the number based on TYPE
Outlook strips phone numbers without types in some cases
CRMs may categorize all emails as “other” without a type
Google Contacts adds inconsistent defaults unless you specify one
Always include TYPE parameters.
- Don’t Forget the UID — It Prevents Duplicate Contacts
If your users ever:
Re-import contacts
Sync between multiple apps
Merge address books
Perform bulk updates
…a missing UID guarantees duplicates.
Best practice:
Generate a UUID for every contact:
UID:123e4567-e89b-12d3-a456-426614174000
Why it matters
Google Contacts uses UID for deduplication
iOS uses it for updates via .vcf re-imports
CRMs rely on it heavily to detect changes
If you don’t generate one, users will inevitably get duplicates.
- Dates Must Follow the vCard Date Format
Birthday? Anniversary? Custom dates? vCard syntax is strict.
Format: YYYY-MM-DD
Not:
MM/DD/YYYY
YYYY/MM/DD
DD-MM-YYYY
Best practice example: BDAY:1985-04-23
If you provide only partial dates or poorly formatted dates, iOS will skip them and Outlook may insert the wrong year.
- Address Fields Are Semicolon-Delimited — Never Comma-Delimited
Developers often get the address field wrong because it looks like CSV in disguise.
Correct format: ADR;TYPE=home:;;123 Main St;Austin;TX;78701;USA
The seven positional fields are:
PO Box
Extended address
Street
City
State
Postal code
Country
Even if you don’t have all seven, you must preserve structure.
Common mistake: ADR:123 Main St, Austin, TX 78701, USA ← Incorrect
This will break in Google Contacts and most CRMs.
- Photo Embedding Should Use Base64 or Hosted Links Properly
If you embed photos incorrectly, you’ll either inflate file size or cause import failures.
Two valid methods:
- Embedded Base64 PHOTO;ENCODING=b;TYPE=JPEG:/9j/4AAQSkZJRgABAQAAAQABAAD…
Pros:
Self-contained
Cons:
Large file size
Some clients reject unusually large vCards
- External URL PHOTO;VALUE=URI:https://example.com/photos/jane.jpg
Pros:
Smaller file size
Faster generation
Allows dynamic updates
Cons:
Some offline imports won’t fetch the image
Best practice
If the file exceeds ~500 KB, prefer external URLs.
- Multi-Contact Files Must Have Properly Delimited Blocks
If you’re exporting multiple contacts inside a single .vcf, every contact needs a complete wrapper:
BEGIN:VCARD … END:VCARD BEGIN:VCARD … END:VCARD
Common mistakes that break imports
Leaving out the END:VCARD before the next contact
Including multiple VERSION fields outside contact blocks
Nesting contacts (yes, some CRMs do this)
Best practice
Treat each contact as fully independent.
- Don’t Include Empty Properties
Empty fields are allowed but discouraged.
Example of what not to do:
TEL: EMAIL: ADR;TYPE=home:;;;;;;
These produce odd behavior across clients, and may cause Google Contacts to silently drop the entire field block.
Best practice
Only write fields that actually contain data.
- Deduplicate Before Exporting
Some address books enforce extremely strict deduping rules.
Before writing a .vcf, normalize and dedupe:
Phone numbers (strip formatting)
Email addresses (case-normalize)
URLs (strip trailing slashes)
Addresses (normalize whitespace)
Custom fields or notes
Deduping before writing results in cleaner, smaller files and prevents confusion during import.
- Test Your Output With Multiple Importers (Not Just One)
Every platform has its own quirks. A vCard that works in iOS may not work in Google Contacts, and vice-versa.
Minimum testing suite
Google Contacts
iOS/macOS Contacts
Outlook (desktop + web)
At least one CRM (HubSpot, Salesforce, or Zoho)
Bonus
Test on Android (OEM apps sometimes differ).
Why this matters
Real-world contact data is messy — testing across platforms uncovers edge cases early.
- Use Tools to Validate Your Output (Or Automate It)
Manually eyeballing .vcf files is painful. A validator saves hours and catches mistakes you won’t see.
CorrectVCF (your app) can:
Parse, validate, and lint .vcf files
Normalize formatting
Repair malformed content
Standardize encoding
Auto-fix common errors
Clean up duplicates
Identify fields incompatible with certain importers
Developers should automate validation in CI or during export routines.
- Provide Both Download and Copy-to-Clipboard Options
If you’re providing vCards through UI, consider offering:
A downloadable .vcf file
A “Copy raw vCard” button
API access for backend automation
This improves developer experience and enables integrations.
- Keep Your Output Predictable and Minimal
The more fields you add, the more likely one importer is going to dislike something.
Best practice: include only the essentials unless your use case requires additional attributes.
Suggested minimal safe set:
BEGIN:VCARD VERSION:3.0 FN:Jane Doe N:Doe;Jane;;; TEL;TYPE=cell:+1-555-123-4567 EMAIL;TYPE=work:[email protected] UID:123e4567-e89b-12d3-a456-426614174000 END:VCARD
If you choose to add extras (photo, org, title, address, anniversary, URLs, custom fields), validate them thoroughly.
- Document Your Export Logic for Future Developers
Most vCard bugs come from “tribal knowledge” disappearing.
Document:
How you generate each field
Which version you follow
How you escape characters
How you encode the file
Which clients you support
Any known limitations or quirks
This prevents regressions in future updates.
Final Thoughts
The vCard format is simple on the surface, but real-world interoperability requires precision. By following these best practices — consistent encoding, correct field structure, proper type metadata, stable UIDs, well-formed addresses, and multi-client testing — you ensure your .vcf exports are robust, predictable, and compatible with all major importers.
If you’re generating vCards at scale, or want an automated way to audit your output, CorrectVCF is built exactly for that — providing validation, repair, and normalization with developer-friendly tooling.