DEV Community

Cover image for How to Read and Write NFC Tags Directly in the Browser with the Web NFC API
VIMAL KUMAR
VIMAL KUMAR

Posted on Originally published at nfctool.org

How to Read and Write NFC Tags Directly in the Browser with the Web NFC API

Near Field Communication (NFC) used to require native iOS or Android mobile applications. With the Web NFC API, modern web apps can now read and write physical NFC tags directly in the browserβ€”no app store downloads needed!
Whether you are building digital business cards (vCards), smart event passes, Wi-Fi credentials sharing, or hardware tap-to-pay experiences, Web NFC unlocks a whole new dimension of web-to-physical interactions.
In this guide, we'll cover:

  • πŸ“± Browser & device support
  • πŸ“– Reading data from NFC tags (NDEFReader.scan)
  • ✍️ Writing text, URLs, and vCards (NDEFReader.write)
  • πŸ”’ Locking tags to read-only (makeReadOnly)
  • ⚠️ Security & permission requirements

πŸ“± Browser & Hardware Requirements

Before writing code, keep in mind:

  • Browser Support: Currently supported natively in Chrome for Android (v89+).
  • Protocol: Requires HTTPS (https://) or localhost during development.
  • Hardware: An Android device with an active NFC chip and standard NDEF-compatible NFC tags (e.g., NTAG213, NTAG215, NTAG216).
  1. Feature Detection Always verify browser support before prompting the user:
function checkNfcSupport() {
  if ('NDEFReader' in window) {
    console.log('βœ… Web NFC is supported!');
    return true;
  } else {
    console.warn('⚠️ Web NFC is not available on this browser/device.');
    return false;
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Reading NFC Tags To start scanning, instantiate NDEFReader and call .scan(). Must be triggered by a user action (e.g., a button click).
async function startScanning() {
  try {
    const ndef = new NDEFReader();
    await ndef.scan();
    console.log('πŸ“‘ NFC Scan started. Bring a tag close to your phone...');
    // Event listener for reading NDEF messages
    ndef.addEventListener('reading', ({ message, serialNumber }) => {
      console.log(`βœ… Tag Detected! Serial Number: ${serialNumber}`);
      for (const record of message.records) {
        console.log(`Record Type: ${record.recordType}`);
        console.log(`MIME Type:   ${record.mediaType || 'N/A'}`);
        // Handle Text Records
        if (record.recordType === 'text') {
          const textDecoder = new TextDecoder(record.encoding);
          const textContent = textDecoder.decode(record.data);
          console.log(`> Text Payload: ${textContent}`);
        }
        // Handle URL Records
        else if (record.recordType === 'url') {
          const textDecoder = new TextDecoder();
          const urlContent = textDecoder.decode(record.data);
          console.log(`> URL Payload: ${urlContent}`);
        }
        // Handle vCards / Custom MIME Types
        else if (record.mediaType === 'text/vcard') {
          const vcardText = new TextDecoder().decode(record.data);
          console.log(`> vCard Content:\n${vcardText}`);
        }
      }
    });
    ndef.addEventListener('readingerror', () => {
      console.error('❌ Error reading NFC tag. Try positioning the tag closer.');
    });
  } catch (error) {
    console.error(`Error starting scan: ${error.message}`);
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Writing Data to NFC Tags Writing to an NFC tag replaces existing NDEF records with new payloads.

A. Writing a Simple URL or Text

async function writeUrlToTag(urlToSave) {
  try {
    const ndef = new NDEFReader();
    await ndef.write({
      records: [
        {
          recordType: 'url',
          data: urlToSave
        }
      ]
    });
    console.log('πŸŽ‰ Successfully wrote URL to NFC tag!');
  } catch (error) {
    console.error(`Write failed: ${error.message}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

B. Writing a Digital Contact Card (vCard)
You can write vCards using mediaType: 'text/vcard':

async function writeVCardToTag(contact) {
  const vcardPayload = [
    'BEGIN:VCARD',
    'VERSION:3.0',
    `FN:${contact.name}`,
    `TEL:${contact.phone}`,
    `EMAIL:${contact.email}`,
    `URL:${contact.website}`,
    'END:VCARD'
  ].join('\r\n');
  try {
    const ndef = new NDEFReader();
    await ndef.write({
      records: [
        {
          recordType: 'mime',
          mediaType: 'text/vcard',
          data: new TextEncoder().encode(vcardPayload)
        }
      ]
    });
    console.log('πŸ“‡ vCard written to NFC card successfully!');
  } catch (error) {
    console.error(`vCard write error: ${error.message}`);
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Locking Tags (Making Them Read-Only) ⚠️ Warning: Making a tag read-only is permanent and irreversible!
async function lockTagPermanently() {
  const confirmed = confirm('Are you sure you want to permanently lock this tag? This cannot be undone!');
  if (!confirmed) return;
  try {
    const ndef = new NDEFReader();
    await ndef.makeReadOnly();
    console.log('πŸ”’ Tag locked successfully. It can no longer be overwritten.');
  } catch (error) {
    console.error(`Failed to lock tag: ${error.message}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

πŸ›‘οΈ Best Practices & Security
User Gesture Requirement: Scanning and writing must be triggered by an explicit user gesture (e.g., button click).
HTTPS Requirement: Modern Web NFC will fail on non-secure contexts (http://), except for local development (localhost).
Handling Timeout: Use AbortController to handle scan timeouts or cancel operations if the user navigates away.

const controller = new AbortController();
async function scanWithTimeout() {
  const ndef = new NDEFReader();
  await ndef.scan({ signal: controller.signal });

  // Abort scan after 15 seconds if no tag is tapped
  setTimeout(() => controller.abort(), 15000);
}
Enter fullscreen mode Exit fullscreen mode

πŸš€ Live Demo & Open Source Tools
Want to test Web NFC directly in your browser without writing boilerplates?

Check out NfcTool.org β€” a free suite of browser-based Web NFC tools for:

πŸ“– Scanning & Inspecting NFC Tags
✍️ Programming NFC Cards
πŸ”’ Locking & Formatting NDEF Payloads
πŸ“‡ Generating NFC vCards & QR Codes
πŸ’¬ What are you building with Web NFC?

Are you experimenting with Web NFC for event check-ins, smart cards, inventory tags, or IoT devices? Share your thoughts and projects in the comments below! πŸ‘‡

Top comments (0)