LDIF to VCF — Move a Thunderbird Address Book to Your Phone
The .ldif file Thunderbird writes when you export an address book is parsed on your device with JavaScript. There is no upload endpoint — the file never leaves this tab. You get a .vcf you can import into a phone or Google Contacts, and a CSV of the same contacts if you want a spreadsheet instead.
Drop your Thunderbird .ldif export here
One record per contact, base64 (::) values decoded — everything runs on your device.
What an LDIF file is, and how Thunderbird exports one
LDIF is the LDAP Data Interchange Format, defined in RFC 2849. It is a text file: one record per directory entry, records separated by blank lines, each line written as attribute: value. A record starts with a dn: line (the distinguished name) followed by the attributes of that entry; in a Thunderbird export one or more objectclass: lines come first, though RFC 2849 itself does not require them. When a value is not plain ASCII, LDIF uses a double colon — attribute:: value — and the value is base64. Long lines are folded: the leftover text continues on the next physical line, which starts with a single space.
Thunderbird's address book speaks this format. Open the Address Book, select the book, and export it as LDIF: on older versions that is Tools → Export; on Thunderbird 102 and later, right-click the address book in the left-hand list (or use its ⋯ menu) → Export, then choose LDIF as the file type. The resulting .ldif uses the standard inetOrgPerson attribute names (cn, sn, givenName, mail, telephoneNumber, and so on) plus Thunderbird's own mozilla* attributes for a second email, a home address, home and work URLs, and similar extras.
This page's parser, parseLdif in lib/ldif.js, implements that RFC 2849 subset: it strips a leading BOM, normalises CR/LF, unfolds space-prefixed continuation lines, ignores # comments and a leading version: N line, splits records on blank lines (and on a new dn: while a record is already open), and decodes :: values as UTF-8. There is no server step. The fixture that locks this behaviour lives in scripts/test-ldif.mjs.
Which LDIF attributes become which vCard fields
Each mapped attribute becomes one field on the contact object that generateVcf in lib/vcard.js already knows how to write. Unmapped attributes are ignored, not copied into a note.
| LDIF attribute | Contact field | vCard 3.0 property |
|---|---|---|
cn, displayName | Full name | FN (and N when no givenName/sn) |
givenName | First name | N (given) |
sn, surname | Last name | N (family) |
mail, mozillaSecondEmail | Email 1, Email 2 | |
telephoneNumber | Phone (work) | TEL;TYPE=WORK |
mobile, cellphone | Phone (cell) | TEL;TYPE=CELL |
homePhone | Phone (home) | TEL;TYPE=HOME |
facsimileTelephoneNumber, fax | Phone (fax) | TEL;TYPE=FAX |
o, company | Company | ORG |
title | Job title | TITLE |
street or streetAddress, l, st, postalCode, c | Work address | ADR (one address) |
mozillaHomeStreet, mozillaHomeLocalityName, mozillaHomeState, mozillaHomePostalCode, mozillaHomeCountryName | Home address (only when no work address) | ADR (one address) |
mozillaWorkUrl, mozillaHomeUrl | Website (work URL wins) | URL |
description | Notes | NOTE |
For single-value fields (name, company, title, notes, each address part, the website) the first occurrence wins; later duplicates of the same attribute are dropped. Emails are the exception: mail and mozillaSecondEmail are both pushed, in file order, skipping only an exact duplicate string. Phone numbers are all kept: telephoneNumber is written as TEL;TYPE=WORK, mobile (and cellphone) as TEL;TYPE=CELL, homePhone as TEL;TYPE=HOME, facsimileTelephoneNumber (and fax) as TEL;TYPE=FAX in vCard 3.0.
One address only. If the record has any attribute of the work set — street / streetAddress, l, st, postalCode, c — the address is built from that set and the mozillaHome* fields are ignored. Otherwise the home set is used. lib/vcard.js then writes that single address as a home address in every version (ADR;TYPE=HOME in 3.0, ADR;HOME in 2.1, ADR;TYPE=home in 4.0), so a work street from LDIF is labelled home after import. For the website, mozillaWorkUrl wins even when mozillaHomeUrl appears first in the file; the home URL is used only when the record has no work URL at all.
Accented names: base64 (cn::) values are decoded
Thunderbird writes any value that contains non-ASCII characters — accents, umlauts, CJK — with a double colon and a base64 payload. The parser does not treat that payload as Latin-1 text: it strips whitespace, runs atob to get the bytes, and decodes those bytes as UTF-8 with TextDecoder. That is why TWFyw61hIEdhcmPDrWE=becomes María García: that literal is the first thing scripts/test-ldif.mjs checks, and the parser's decode of it is asserted right after.
LDIF allows any long line — a base64 value included — to be folded onto a continuation line that starts with a single space. The parser joins those pieces before the decode, so a cn:: value split across two physical lines still round-trips to the original name. An empty value, a :< URL-reference line, or a comment starting with # is skipped.
On the way out, vCard 3.0 and 4.0 keep the name as plain UTF-8 (FN:María García). vCard 2.1 cannot assume UTF-8 on old handsets, so lib/vcard.js encodes that same name as quoted-printable with CHARSET=UTF-8 — Mar=C3=ADa Garc=C3=ADa. That is the only difference the version dropdown makes for accented text; the LDIF parse is the same regardless of which vCard version you download.
What is not carried over
The parser reads a fixed list of attributes and ignores everything else. These are not bugs in the vCard writer; they never reach it:
- Photos. No photo attribute is read, so nothing reaches a vCard
PHOTOline. AjpegPhotoin the LDIF is dropped, including the:<URL-reference form. mozillaNickname,mozillaCustom1–4,birthyear/birthmonth/birthday,ou(department),pager,mozillaUseHtmlMail,nsAIMid,modifytimestamp.- Second street lines:
mozillaHomeStreet2andmozillaWorkStreet2are ignored. Onlystreet/streetAddressormozillaHomeStreetis used. - The home address when any work-address attribute exists; the home URL when a work URL exists. One address, one URL.
- More than two emails are kept on the contact object and written into the .vcf, but the CSV export only has Email 1 and Email 2 columns, so a third address will not show in the spreadsheet.
Mailing lists are skipped on purpose. Thunderbird stores a list as a record whose objectclass includes groupOfNames, with member: lines pointing at contacts that are already in the same file as their own records. Converting the list as if it were a person would create a dummy card named after the list; the parser increments the skipped counter instead. Records that have no full name, first name, last name, email or phone — a leftover dn with only objectclass and modifytimestamp, for example — are skipped and counted the same way.
Importing the .vcf
The download is a standard vCard file (one BEGIN:VCARD…END:VCARD block per contact, CRLF line endings, the version you picked). From the point where you have that .vcf, the import steps are the same as for any other vCard this site produces. Use the Android import guide, the iPhone import guide, the iCloud contacts guide, or the Google Contacts guide — they all pick up from "now you have a .vcf".
If you want a spreadsheet instead of a phone import, use the Download CSV button on this page (UTF-8 with a BOM, so Excel keeps María as María). To get a native .xlsx, download the .vcf and run it through the VCF to Excel converter.
LDIF to VCF — FAQ
Where is the LDIF export option in Thunderbird?
In Thunderbird 102 and later, open the Address Book, right-click the address book in the left-hand list (or use its ⋯ menu) and choose Export; set the file type to LDIF. Older versions put the same command on the Tools menu: Address Book → select the book → Tools → Export → LDIF. The file this page reads is that export: one record per contact, each starting with a dn: line.
Is my Thunderbird address book uploaded anywhere?
No. The parser is JavaScript that runs in this tab — there is no upload endpoint at all. After the page has loaded you can disconnect from the internet and still drop a .ldif, preview the contacts, and download a .vcf or a CSV. Nothing in lib/ldif.js, lib/vcard.js or the converter component makes a network request with your file.
Why do some lines in my .ldif start with cn:: instead of cn:?
A double colon is how LDIF (RFC 2849) marks a base64 value. Thunderbird writes any attribute that contains non-ASCII characters that way — accented names, umlauts, CJK — so cn:: TWFyw61hIEdhcmPDrWE= is María García. The parser strips whitespace from the base64, decodes it to bytes with atob, and decodes those bytes as UTF-8. Folded continuation lines that start with a single space are joined before that decode.
Which vCard version should I choose?
Leave vCard 3.0 selected unless you have a reason not to: that is the version Google Contacts, iPhone and Android import. Choose 2.1 only for old feature phones that expect quoted-printable names (the 2.1 download writes CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE for non-ASCII text, which is what lib/vcard.js does). Choose 4.0 only when an app specifically asks for it.
Why is the contact count lower than the number of records in the file?
Two kinds of record are skipped and counted on the result line: mailing lists, which Thunderbird stores as objectclass groupOfNames (their members are already separate contact records in the same file), and records that have no full name, first name, last name, email or phone — for example a leftover dn with only objectclass and modifytimestamp. The number after the parsed count is that skip total.
Can I get a CSV or Excel file instead of a vCard?
Yes. After parsing, Download CSV writes the same contacts using the columns this site uses everywhere else (First Name, Last Name, Full Name, two phone columns with types, two emails, company, job title, street, city, state, ZIP, country, website, notes), as UTF-8 with a BOM so Excel opens accents correctly. For a native .xlsx, download the .vcf and run it through this site's VCF to Excel converter.
Does this work with LDIF from an LDAP server or another program?
The parser follows the RFC 2849 subset described on this page and maps the standard inetOrgPerson attributes cn, sn, givenName, mail, telephoneNumber, mobile, homePhone, facsimileTelephoneNumber, o, title, street, l, st, postalCode and c, so an ldapsearch export that uses those names will map the same way. mozilla* attributes (home address, home/work URLs, mozillaSecondEmail) are Thunderbird extras and will simply not be present in a generic LDAP dump. This converter has only been tested with the fixture in scripts/test-ldif.mjs.
Parser behaviour on this page is covered by the fixture in scripts/test-ldif.mjs. Last checked: August 26, 2026. About this site