Skip to content

Instantly share code, notes, and snippets.

@ichernev
Created November 6, 2025 23:13
Show Gist options
  • Select an option

  • Save ichernev/53582083a9144556b4e0dbf6df2ef51c to your computer and use it in GitHub Desktop.

Select an option

Save ichernev/53582083a9144556b4e0dbf6df2ef51c to your computer and use it in GitHub Desktop.
Python script that converts VCF into CSV
# import vcf
# with open('contacts.vcf', 'r') as f:
# vcf_reader = vcf.Reader(f)
# i = 0
# for record in vcf_reader:
# print('{} {}'.format(i, record))
# i += 1
import json
import quopri
import csv
def dec_str(kp, v):
if 'ENCODING=QUOTED-PRINTABLE' in kp:
cs = list(filter(lambda p: p.startswith('CHARSET='), kp))
if len(cs) == 1:
csx = cs[0][len('CHARSET='):]
else:
csx = 'UTF-8'
return quopri.decodestring(v).decode(csx)
else:
return v
def read_vcf(filename):
contacts = []
with open('contacts.vcf', 'r') as f:
inB64 = False
contact = None
for line in f:
line = line.strip()
if line == 'BEGIN:VCARD':
contact = {}
continue
if line == 'VERSION:2.1':
continue
if inB64:
if not line:
inB64 = False
continue
# accum b64 here
try:
kraw, vraw = line.split(':', 1)
except:
print('BAD line was {}'.format(line))
continue
kp = kraw.split(';')
vp = vraw.split(';')
if 'ENCODING=BASE64' in kp:
inB64 = True
continue
if kp[0] == 'N':
contact['last_name'] = dec_str(kp, vp[0])
contact['first_name'] = dec_str(kp, vp[1])
elif kp[0] == 'FN':
contact['full_name'] = dec_str(kp, vp[0])
elif kp[0] == 'TEL':
phones = contact.get('phones', [])
phones.append(vp[0])
if 'PREF' in kp and len(phones) > 1:
phones[0], phones[-1] = phones[-1], phones[0]
contact['phones'] = phones
elif kraw == 'END' and vraw == 'VCARD':
contacts.append(contact)
# print(json.dumps(contact, indent=4))
# print('----')
continue
else:
print('UNKNOWN key {}'.format(kp[0]))
return contacts
def dump_in_csv(contacts, filename):
with open(filename, 'w', newline='') as f:
csv_w = csv.writer(f, delimiter=',',
quotechar='"', quoting=csv.QUOTE_MINIMAL)
csv_w.writerow(['First Name', 'Last Name', 'Full Name',
'Phone', 'Phone 2', 'Phone 3'])
for c in contacts:
phones = c.get('phones', [])
get_phone = lambda i: phones[i] if i < len(phones) else ''
csv_w.writerow([c.get('first_name', ''), c.get('last_name', ''),
c.get('full_name', ''), get_phone(0),
get_phone(1), get_phone(2)])
dump_in_csv(read_vcf('contacts.vcs'), 'contacts.csv')
# for c in filter(lambda c: len(c.get('phones', [])) > 1, contacts):
# print(json.dumps(c, indent=4))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment