vCard QR Code Generation and Scanning with JavaScript

vCard, also known as VCF (“Virtual Contact File”), is a file format standard for electronic business cards. The following is an example of the content of a vCard file:

BEGIN:VCARD
VERSION:4.0
FN:Simon Perreault
N:Perreault;Simon;;;ing. jr,M.Sc.
BDAY:--0203
GENDER:M
EMAIL;TYPE=work:simon.perreault@viagenie.ca
END:VCARD

Widely used in business and personal networking, vCards can be shared via email, messaging apps, NFC, or cloud links. One of the most convenient and modern methods is QR codes, which allow instant contact exchange with a simple scan. If you scan the following QR code with your iPhone’s camera, you will be prompted to add a contact.

vcard qr code

vcard-qr-code-scanning-with-ios-camera

In this article, we are going to build an HTML page to generate vCard QR codes and another page to scan the QR code based on the Dynamsoft Barcode Reader SDK. An advantage of having our own web app to scan the vCard is that we can integrate with CRM systems like Salesforce and Dynamics 365 to facilitate contact management.

Demo video:

Prerequisites

Get your trial key.

Request a Trial License

Demo: DLS2eyJvcmdhbml6YXeyJo34567AwMDAxLTEwM34XphdGlvbk812345AxIn0=
Reveal

This generates an online license that collects data regarding your usage of the SDK. If you prefer an offline license key, please contact us.​

Your Trial License

DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTEwMTIwMDkzNiIsIm9yZ2FuaXphdGlvbklEIjoiMjAwMDAxIn0=
Copy
Copied!

Request a Trial License - Successful

The license will be sent to your email immediately. If you don't see it in your inbox, please check your junk/spam folder as well.

Generate vCard QR Code

We are going to use two third-party libraries:

  1. Create a new HTML file and include the above libraries.

    <!DOCTYPE html>
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>vCard QR Code Generator</title>
      <style>
      </style>
      <script type="text/javascript" src="qrcode.js"></script>
      <script type="module">
        import VCard from 'https://cdn.skypack.dev/vcard-creator'
        window.VCard = VCard;
      </script>
    </head>
    <html>
    <body>
      <div id="app">
        <h2>vCard QR Code Generator</h2>
      </div>
      <script>
      </script>
    </body>
    </html>
    
  2. Create a form to enter the contact info.

    <div class="form">
      <label>
        First name:
        <input type="text" id="firstName"/>
      </label>
      <label>
        Last name:
        <input type="text" id="lastName"/>
      </label>
      <label>
        Phone:
        <input type="text" id="phone"/>
      </label>
      <label>
        Email:
        <input type="text" id="email"/>
      </label>
      <label>
        Company:
        <input type="text" id="company"/>
      </label>
      <label>
        Job title:
        <input type="text" id="jobTitle"/>
      </label>
      <label>
        Website:
        <input type="text" id="website"/>
      </label>
      <button id="generateButton">Generate</button>
    </div>
    
  3. Generate the QR code using the entered contact info.

    <div id="placeHolder"></div>
    <script>
    document.getElementById("generateButton").addEventListener("click",generateQRCode);
    function generateQRCode(){
      const card = new VCard()
      const firstName = document.getElementById("firstName").value;
      const lastName = document.getElementById("lastName").value;
      const phone = document.getElementById("phone").value;
      const company = document.getElementById("company").value;
      const jobTitle = document.getElementById("jobTitle").value;
      const website = document.getElementById("website").value;
      const email = document.getElementById("email").value;
      card.addName(lastName, firstName, "", "", "")
        .addCompany(company)
        .addJobtitle(jobTitle)
        .addEmail(email)
        .addPhoneNumber(phone, 'WORK')
        .addURL(website)
      const vcf = card.toString();
      console.log(vcf);
      generateQR(vcf);
    }
    function generateQR(content){
      try {
        var typeNumber = 0;
        var errorCorrectionLevel = 'L';
        var qr = qrcode(typeNumber, errorCorrectionLevel);
        qr.addData(content);
        qr.make();
        var placeHolder = document.getElementById('placeHolder');
        placeHolder.innerHTML = qr.createSvgTag();  
      } catch (error) {
        alert(error);
      }
    }
    </script>
    
  4. We can also generate the QR code using an existing vcf file.

    <button id="generateWithExistingButton">Generate with an existing vcf file</button>
    <input style="display:none;" type="file" id="file" onchange="loadFromFile();" accept=".vcf"/>
    <script>
    document.getElementById("generateWithExistingButton").addEventListener("click",function(){
      document.getElementById("file").click();
    });
    
    function loadFromFile(){
      let fileInput = document.getElementById("file");
      let files = fileInput.files;
      if (files.length == 0) {
        return;
      }
      let file = files[0];
      fileReader = new FileReader();
      fileReader.onload = function(e){
        generateQR(e.target.result);
      };
      fileReader.onerror = function () {
        console.warn('oops, something went wrong.');
      };
      fileReader.readAsText(file);
    }
    </script>
    

Please note that a QR code can only contain about 2 KBs of data. If you need to transfer more data, you can try the animated QR codes approach.

Scan vCard QR Code

Next, let’s create a page to scan the vCard QR code.

New HTML File

Create a new HTML file with the following content:

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>vCard QR Code Scanner</title>
  <style>
  h2 {
    text-align: center;
  }

  #app {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  #cameraView {
    width: 100%;
    height: 60vh;
  }
  </style>
</head>
<html>
<body>
  <div id="app">
    <h2>vCard Scanner</h2>
    <button id="startScanBtn">Start Scanning</button>
    <button id="readFromImageBtn">Read from an Image</button>
    <input id="fileInput" type="file" style="display:none;"/>
    <div id="status">Loading...</div>
    <div id="cameraView"></div>
    <div id="result"></div>
  </div>
</body>
</html>

Add Dynamsoft Barcode Reader

Include the library of Dynamsoft Barcode Reader with the following line of code:

<script src="https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@10.4.2000/dist/dbr.bundle.js"></script>

Then, initialize Dynamsoft Barcode Reader.

  1. Initialize the license. You can apply for a license here.

    Dynamsoft.License.LicenseManager.initLicense("LICENSE-KEY");
    
  2. Load the WASM file.

    Dynamsoft.Core.CoreModule.loadWasm(["dbr"]);
    
  3. Create an instance of Capture Vision Router to call Dynamsoft Barcode Reader.

    let cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance();
    

Start Scanning from the Camera

  1. Initialize Camera Enhancer and bind its viewer to a container.

    let cameraView = await Dynamsoft.DCE.CameraView.createInstance();
    let cameraEnhancer = await Dynamsoft.DCE.CameraEnhancer.createInstance(cameraView);
    document.querySelector("#cameraView").append(cameraView.getUIElement());
    
  2. Use Camera Enhancer as the input of the capture vision router so that it can fetch frames from the cameras for reading barcodes.

    cvRouter.setInput(cameraEnhancer);
    
  3. Add a result receiver to receive the scanning results.

    cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => {
      displayResults(result);
    }});
    
    function displayResults(result){
      if (result.barcodeResultItems.length > 0) {
        let container = document.getElementById("result");
        let item = result.barcodeResultItems[0];
        console.log(item);
      }
    }
    
  4. Start scanning after the scan button is clicked.

    let templateName = "ReadSingleBarcode"
    await cameraEnhancer.open();
    await cvRouter.startCapturing(templateName);
    

Parse vCard Content

Next, parse the vCard content and display the contact info.

<!-- https://github.com/Heymdall/vcard/ -->
<script type="text/javascript" src="vcf.js"></script>
<script>
function formatedContactInfo(barcodeText) {
  try {
    let parsed = parse(barcodeText);
    let presetKeys = {"fn":"Full name","org":"Organization","title":"Job Title","url":"URL","tel":"Tel","email":"Email"};
    let str = "";
    for (let index = 0; index < Object.keys(presetKeys).length; index++) {
      const key = Object.keys(presetKeys)[index];
      const value = presetKeys[key];
      if (key in parsed) {
        let appendedValue = "";
        let valueArray = parsed[key];
        valueArray.forEach(valueObject => {
          appendedValue = appendedValue + valueObject.value + "\n";
        });
        str = str + value + ": " +appendedValue.trim() + "\n";
      }
    }
    vCardContent = barcodeText;
    document.getElementsByClassName("buttons")[0].removeAttribute("hidden");
    return str;
  } catch (error) {
    return "Invalid vCard."
  }
}
</script>

Download as a VCF File

We can download the vCard as a .vcf file. It can be opened by the system’s contact app.

function downloadText(){
  let filename = 'scanned.vcf';
  let link = document.createElement('a');
  link.style.display = 'none';
  link.setAttribute('target', '_blank');
  link.setAttribute('href', 'data:text/vcard;charset=utf-8,' + encodeURIComponent(vCardContent));
  link.setAttribute('download', filename);
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

Read QR Code in an Image

Apart from live scanning, we can also read vCard QR codes in an image.

Add events for selecting an image file. After the image is selected, read the barcodes in it using the capture method.

document.getElementById("readFromImageBtn").addEventListener("click",function(){
  if (initialized) {
    document.getElementById("fileInput").click();
  }else{
    alert("Please wait for the initialization.");
  }
});
document.getElementById("fileInput").addEventListener("change",async function(){
  let files = document.getElementById("fileInput").files;
  if (files.length>0) {
    let file  = files[0];
    let result = await cvRouter.capture(file,templateName);
    displayResults(result);
  }
})

All right, we’ve finished the demo.

Source Code

Check out the source code to have a try: