vCard for Developers

I’ve been researching vCard for a project involving contacts management. This is a quick overview on vCard aimed at developers, with a demo and stealing the example from wikipedia’s vCard entry. The official standard is here.

The Format

vCard is a standard for representing contact information, the kind of info you would see for a contact in an address book or email application – name, address, and so on. By convention, the file suffix is “.vcf”. The info is represented in a text file format as shown below:

BEGIN:VCARD
VERSION:2.1
N:Gump;Forrest (Name)
FN:Forrest Gump (Full Name)
ORG:Gump Shrimp Co.
TITLE:Shrimp Man
TEL;WORK;VOICE:(111) 555-1212
TEL;HOME;VOICE:(404) 555-1212
ADR;WORK:;;100 Waters Edge;Baytown;LA;30314;United States of America
LABEL;WORK;ENCODING=QUOTED-PRINTABLE:100 Waters Edge=0D=0ABaytown, LA 30314=0D=0AUnited States of America
ADR;HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America
LABEL;HOME;ENCODING=QUOTED-PRINTABLE:42 Plantation St.=0D=0ABaytown, LA 30314=0D=0AUnited States of America
EMAIL;PREF;INTERNET:[email protected]
REV:20080424T195243Z
END:VCARD

As you can see, the format is an ugly mainframe-style format that belies vCard’s 1995 birthdate. If it was created a year or two later, it likely would have been a prettier XML format. But don’t be scared, it’s mostly harmless. You basically have field-value pairs separated by “:”. The standard defines all possible fields and the format for their values.

The Fields

The fields defined are: FN (full name – e.g. “Mr. Homer J. Simpson”), N (name – e.g. “Simpson;Homer”), NICKNAME, PHOTO, BDAY (birthday), ADR, LABEL, TEL, EMAIL, MAILER, TZ, GEO (lat/long co-ordinates), TITLE, ROLE, LOGO, AGENT (e.g. a secretary or personal assistant – this is a recursive vCard instance!), ORG, CATEGORIES, NOTE, PRODID (which product created the vCard), REV (a revision ID for this vcard instance), SORT-STRING (the “primary key” on which this record should be sorted, e.g. if you want ‘Van Winkle’ to be sorted as ‘Winkle’), SOUND, URL, UID, VERSION (the version of vCard used to generate this vCard), CLASS (a security access level for this vCard instance – e.g. is it public, protected, private?), KEY (a public key, e.g. you could use it if you wanted to send the contact something encrypted). The only mandatory fields here are FN and N (the two most obscurely named fields, naturally ;)).

Each field-value pair is something like a database record or an object instance, insofar as it includes a number of values. I guess the standard could have avoided this by defining 200 different field names, but instead they grouped related attributes together into the same field. So you end up with just a single “name” field (“N”), which is actually an aggregation of several fields. e.g. ” N:Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.” contains surname, first name, other names, title, and honorifics.

Similarly, field names are not always just a single word, but can also be qualified by type. Therefore “TEL;WORK;VOICE;PREF” is equivalent to “TEL;TYPE=WORK,VOICE,PREF” and also “TEL;TYPE=WORK,TYPE=VOICE,TYPE=PREF”. (The first form actually appears in the wikipedia example, but the standard talks about the second and third form, so any parser would have to read all of them.). The multiple types are effectively tags/keywords, i.e. the telephone number here is at once a work number, a number supporting voice interaction, and a preferred usage number.

Fields like logo and photo can either be a URL or binary data embedded directly in the VCARD.

See the official standard for full details.

MIME Gubbins: How to Serve vCard from your Web App

If you ever show contacts in your web app, it’s polite to include a vCard export option as users will appreciate the ability to pluck it off the site and into their preferred desktop app. I found serving it to be remarkably easy.

The demo is here

<?
  header('Content-Type: text/x-vcard; charset=utf-8');
  header('Content-Disposition: attachment; filename="vcard-example.vcf"');
?>
BEGIN:VCARD
VERSION:2.1
N:Gump;Forrest
FN:Forrest Gump
...
etc
....
END:VCARD

See? Just output those two headers, then bust out the vCard. The demo successfully opens in Apple Address Book and MS Outlook.

Apple Address Book

MS Outlook

So it works if you’re a Mac or a PC. Neat-O.

Portability, Limitations, and Variations

The great thing about standards is there are so many to choose from, as many a cynic has observed. The other great thing about most standards is they give you so much room for creativity, as this cynic responded. vCard is no exception and can be interpreted in different ways (whether or not these ways conform to the spec I don’t know, and is not especially relevant for real-world developers).

In particular, some people think a vCard file can include only one record, while others think it can include any number of records. I made a second demo to test this. The two-card demo is here. It contains one VCARD after another, as shown below. Well, Apple Address Book likes it and opens up both contacts, while MS Outlook ignores the second. So there.

<?
  header('Content-Type: text/x-vcard; charset=utf-8');
  header('Content-Disposition: attachment; filename="vcard-example.vcf"');
?>
BEGIN:VCARD
VERSION:2.1
N:Gump;Forrest
....
END:VCARD
BEGIN:VCARD
VERSION:2.1
N:Fump;Gorrest
....
END:VCARD

Furthermore, there are “extensions”, which are new property types that go beyond the standard and are used by certain applications. Wikipedia identifies a veritable menagerie of extensions, including such species as X-MANAGER for manager details; X-AIM/X-MSN/X-ICQ/X-GADUGADU (awesome!)/etc for IM details, and X-ASSISTANT for assistant details (they probably forgot about the AGENT property). any other properties are prefixed with the company who introduced them, leading to the elegantly named X-FUNAMBOL-YOMIFIRSTNAME property (this will soon become the sixth page on the internet to use that term).

Related Standards

vCard is closely related to a wider standard around directory formats, RFC 2425. This standard defines the basic, mainframe, field-value pair structure, as well as some basic types – SOURCE (source for the record, e.g. an LDAP server), NAME (name of the record, which will usually be the same a the vCard “N” field), PROFILE (vaguely defined as something about “how the record will be used”), BEGIN, END. BEGIN and END naturally appear in all vCards, but examples I’ve seen don’t use the other three types.

This W3C note attempts to XMLise vCard within an RDF framework.

hCard attempts to HTMLise vCard as part of the more-lightweight-than-RDF microformats initiative. (examples).

iCalendar, aka iCal and formally vCal (which sounds like vCard doesn’t it?) came from the Versit consortium around the same time as vCard…both intended for similar types of applications. iCal is about exchanging event information.

7 thoughts on vCard for Developers

  1. The content type isn’t specified in the vCard document? HTTP tells the content type over the web, but what do you do with vCard files in your file system? Guess utf-8? or windows-1252? or latin-1?

    If it were XML that wouldn’t be a problem.

  2. Pingback: microformatique - a blog about microformats and “data at the edges” : vCard - the nitty gritty

  3. Pingback: vCard Links That Actually Explain the vCard Format | rm core

  4. Pingback: vCard by Tech Ramblings

  5. The following windows batch file can be used to call an awk script which will split a single .vcf file into a file per record and follows below. After splitting the file, drag 70 contact files at a time into the Outlook Contacts page from windows file manager and click on the save button in each window that appears.

    REM ############################################## REM # Purpose: Run the Contacts.awk script REM # Author: MB REM # Date: 2016/04/03. REM # Uses GnuWin32 binary executable command “awk” from SourceForge.net REM ##############################################

    set BIN=”C:\Users\YourUserName\GnuWin32\bin”

    %BIN%\awk -f Contacts_split.awk PIM00001.vcf

    REM End of file.————————————————————

    The Contacts_split.awk awk script follows:

    #

    #

    Purpose: Split the Contacts.vcf file into separate files by record type.

    Author: mbesaans

    Date: 2016/04/03.

    Note: For each record in the input, this program tests for matches of the

    pattern of the AWK program

    The patterns are tested in the order that they occur in the program.

    #

    #

    Find the start of each record and write it to a new .vcf file with the record number appended to the name.

    /^BEGIN\:VCARD$/ { file_appendix++; output_file = “x” file_appendix “.vcf” } { print $0 >> output_file }

    Print the total records read.

    END { print “Total input records: ” file_appendix }

Leave a Reply