Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

vcard-ts

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vcard-ts

A simple, modern TypeScript library for VCard 3.0 (RFC 2426) with browser and Node.js support

latest
Source
npmnpm
Version
2.0.0
Version published
Maintainers
1
Created
Source
vcard-ts header image

vcard-ts

A simple, modern TypeScript library for creating VCard 3.0 (RFC 2426) formatted strings. Zero dependencies, fully typed, and works in both browser and Node.js environments.

Features

  • RFC 2426 Compliant - Strictly follows the VCard 3.0 specification
  • 🎯 Simple API - No complex builder patterns, just plain objects
  • 🔒 Fully Typed - Complete TypeScript type definitions
  • 📦 Zero Dependencies - Lightweight and fast
  • 🌐 Universal - Works in browser and Node.js
  • Modern - ESM + CommonJS, tree-shakeable
  • 🧪 Well Tested - Comprehensive test coverage
  • 🍏 iOS URL Labels - Supports multiple URLs with human-friendly labels in Apple Contacts

Why VCard 3.0?

While VCard 4.0 exists, as of right now 3.0 remains the most widely supported format.

Installation

npm install vcard-ts

Usage

Basic Example

import { formatVCard, type VCard } from 'vcard-ts';

const vcard: VCard = {
  version: '3.0',
  formattedName: 'John Doe',
  name: {
    familyName: 'Doe',
    givenName: 'John',
  },
};

const vcardString = formatVCard(vcard);
console.log(vcardString);

Output:

BEGIN:VCARD
VERSION:3.0
FN:John Doe
N:Doe;John;;;
END:VCARD

Character Set Support

Some legacy vCard consumers expect or require a CHARSET=... parameter on text properties.

Note: CHARSET is not defined in RFC 2426 itself; this library supports it as a legacy interoperability option.

By default, the formatter assumes UTF-8 and does not emit any CHARSET parameters.

import { formatVCard, type VCard } from 'vcard-ts';

const vcard: VCard = {
  version: '3.0',
  formattedName: 'José García',
  name: {
    familyName: 'García',
    givenName: 'José',
  },
};

const vcardString = formatVCard(vcard);
console.log(vcardString);

Output:

BEGIN:VCARD
VERSION:3.0
FN:José García
N:García;José;;;
END:VCARD

If you need legacy interoperability, you can explicitly declare a charset via formatter options:

const vcardString = formatVCard(vcard, { charset: 'ISO-8859-1' });

Photo/Logo/Sound

You can include media either as a URI reference or inline base64 data:

// URI Reference
const vcardWithPhoto: VCard = {
  version: '3.0',
  formattedName: 'Jane Smith',
  name: { familyName: 'Smith', givenName: 'Jane' },
  photo: {
    uri: 'https://example.com/photo.jpg',
    mediaType: 'JPEG',
  },
};

// Inline Base64 (must be pre-encoded)
const vcardWithInlinePhoto: VCard = {
  version: '3.0',
  formattedName: 'Jane Smith',
  name: { familyName: 'Smith', givenName: 'Jane' },
  photo: {
    value: 'base64EncodedDataHere...',
    encoding: 'b',
    mediaType: 'JPEG',
  },
};

Android / Google Contacts Import Note

Some Android/Google Contacts imports can mis-parse folded lines (RFC 2426 line folding with CRLF + space), especially for structured properties like ADR. If you see parts of the address appear as a name suffix or the address disappears, disable folding:

import { formatVCard, type VCard } from 'vcard-ts';

const vcard: VCard = {
  version: '3.0',
  formattedName: 'Jane Smith',
  name: { familyName: 'Smith', givenName: 'Jane' },
  addresses: [
    {
      street: '100 Tech Plaza',
      locality: 'San Francisco',
      region: 'CA',
      postalCode: '94105',
      country: 'United States of America',
      types: ['work'],
    },
  ],
};

// Keeps ADR on a single line (no folded continuations)
const vcardString = formatVCard(vcard, { foldLines: false });

Special Characters

The library automatically escapes special characters according to RFC 2426:

const vcard: VCard = {
  version: '3.0',
  formattedName: 'Test; User, with\\special chars',
  name: {
    familyName: 'User',
    givenName: 'Test',
  },
  note: 'Line 1\nLine 2',
};

// Special characters are automatically escaped:
// ; -> \;
// , -> \,
// \ -> \\
// newline -> \n

Multiple URLs + iOS Labels

Many consumers (including iOS Contacts) support multiple URL entries but won’t display a meaningful label unless you use Apple’s extension fields.

This library supports that via urls, emitting itemN.URL + itemN.X-ABLabel. The item1., item2., etc. prefix is the vCard group syntax: it scopes multiple related lines under the same group name. So that item1.X-ABLabel can be associated with item1.URL.

The X-ABLabel property is an Apple-specific X- extension used by iOS Contacts to display a human-friendly label for the preceding itemN.URL field (e.g. “LinkedIn”, “Website”). This is usually not supported on Android.

import { formatVCard, type VCard } from 'vcard-ts';

const vcard: VCard = {
  version: '3.0',
  formattedName: 'Michael Wolz',
  name: { familyName: 'Wolz', givenName: 'Michael' },
  urls: [
    { value: 'https://www.linkedin.com/in/michaelwolz', type: 'LinkedIn' },
    { value: 'https://michaelwolz.de', type: 'Website' },
  ],
};

console.log(formatVCard(vcard));

Output (excerpt):

item1.URL:https://www.linkedin.com/in/michaelwolz
item1.X-ABLabel:LinkedIn
item2.URL:https://michaelwolz.de
item2.X-ABLabel:Website

Notes:

  • iOS: shows both URLs and the labels.
  • Android: typically shows both URLs, but often ignores the X-ABLabel labels.
  • vCard 4.0 supports richer, standardized URL typing, but vCard 3.0 tends to have broader real-world compatibility; this is a practical workaround.

API Reference

Type: VCard

The main VCard type representing a complete vCard object.

Required Fields:

  • version: '3.0' - Must be "3.0"
  • formattedName: string - Formatted name (FN property)
  • name: Name - Structured name (N property)

Optional Fields:

See the TypeScript definitions for the complete list of optional fields including:

  • Identification: nickname, photo, birthday
  • Delivery Addressing: addresses, labels
  • Telecommunications: phones, emails, mailer
  • Geographical: timezone, geo
  • Organizational: title, role, logo, agent, organization
  • Explanatory: categories, note, productId, revision, sortString, sound, url, uid
  • URLs: url (single) and urls (multiple + optional iOS labels)
  • Security: class, key

Function: formatVCard

function formatVCard(vcard: VCard, options?: { charset?: 'UTF-8' | 'ISO-8859-1' | 'US-ASCII' }): string;

// You can also disable RFC line folding for Android/Google Contacts compatibility:
// formatVCard(vcard, { foldLines: false })

Converts a VCard object into an RFC 2426 compliant VCard 3.0 string.

Parameters:

  • vcard: VCard - The VCard object to format
  • options?: { charset?: 'UTF-8' | 'ISO-8859-1' | 'US-ASCII'; fold?: boolean } - Optional formatting options
    • charset - (Legacy) Charset to declare via CHARSET parameters on text properties. If omitted, UTF-8 is assumed and no CHARSET is emitted.
    • foldLines - Whether to apply RFC 2426 line folding (75 characters, CRLF + space). Default: true. Set to false if Android/Google Contacts mis-parses folded ADR lines.

Returns:

  • string - RFC 2426 compliant VCard string with CRLF line endings

Features:

  • Automatic text escaping for special characters
  • Line folding for lines longer than 75 characters
  • CHARSET parameters on text properties (legacy; only emitted when explicitly requested)
  • Proper formatting of all VCard 3.0 properties
  • Date/DateTime formatting

Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Build the library
npm run build

# Type check
npm run typecheck

# Lint code
npm run lint

# Format code
npm run format

Browser Support

Works in all modern browsers and Node.js 16+.

Contributing

Contributions are welcome! Please ensure all tests pass and follow the existing code style.

References

  • RFC 2426 - vCard MIME Directory Profile
  • MIME Directory Profile (RFC 2425)

Keywords

vcard

FAQs

Package last updated on 18 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts