Web NFC API

Enable Near Field Communication directly in web browsers. Read and write NFC tags without native applications.

Understanding NFC and the Web NFC API

Near Field Communication (NFC) enables wireless communication between two devices at close proximity, typically less than a few centimeters. Operating at 13.56 MHz, NFC is an international standard (ISO/IEC 18092) that defines an interface and protocol for simple wireless interconnection of closely coupled devices.

The Web NFC API allows web applications to interact with NFC tags, providing a powerful tool for bridging the gap between the physical and digital worlds directly from the browser. This API enables selected use cases based on NFC technology, with the current scope focused specifically on NDEF (NFC Data Exchange Format) interactions.

The technology works through magnetic induction, where the reader emits a small electric charge creating a magnetic field that powers passive devices and enables data exchange. This electromagnetic coupling allows NFC tags--which contain no power source of their own--to transmit data simply by being brought within range of a powered device.

Key Requirements for Web NFC

The API requires several important conditions for operation:

  • Secure Context (HTTPS): NFC interactions must be protected from unauthorized access
  • Page Visibility: The webpage must be visible when NFC interactions occur
  • User Permission: Explicit consent is required before NFC operations can proceed

These requirements ensure that NFC functionality is used safely and with user awareness, preventing malicious websites from accessing NFC data without consent. Implementing these security measures is a core aspect of our secure web development practices.

Core Web NFC Capabilities

The Web NFC API provides essential operations for interacting with NFC tags

Read NFC Tags

Retrieve NDEF messages from NFC tags when devices come within range, enabling access to stored information like URLs, text, or custom data formats.

Write to NFC Tags

Program NFC tags with custom data including URLs, text messages, JSON data, and smart poster records for rich content sharing.

Make Tags Read-Only

Permanently lock NFC tags against future modifications, ensuring content integrity for ticketing, authentication, and product labeling applications.

Multi-Record Support

Work with complex NDEF messages containing multiple records of different types, including embedded smart posters and custom data structures.

NDEF: The NFC Data Exchange Format

NDEF (NFC Data Exchange Format) is a lightweight binary message format standardized by the NFC Forum that enables consistent data exchange across NFC devices and tags. An NDEF message encapsulates one or more application-defined NDEF records, and these messages can be stored on NFC tags or exchanged between NFC-enabled devices.

NDEF Record Structure

Each NDEF record is a binary structure containing:

  • Header Byte: Contains flags for message begin/end, chunking, short record, and ID length
  • Type Length: Byte size of the type field
  • Payload Length: Size of the payload (1 byte for short records, 4 bytes for normal)
  • Type Field: Describes the payload type (T, U, Sp, etc.)
  • ID Field: Optional record identifier
  • Payload Field: The actual application data

TNF: Type Name Format Values

The TNF (Type Name Format) field indicates the format of the type name and describes the NDEF record payload type. Seven TNF values are defined, each representing a different record category:

TNF ValueDescriptionUse Case
0Empty record (no content)Placeholder or initialization
1NFC Forum well-known typeText, URL, smart poster records
2MIME type recordBinary data with MIME type
3Absolute-URL recordComplete URL in type field
4NFC Forum external typeApplication-specific data (urn:nfc:ext:domain:type)
5Unknown recordOpaque data without MIME type
6Unchanged (chunk continuation)Multi-record chunked payloads

For most web applications, TNF value 1 (well-known types) covers common use cases like text and URL records. External types (TNF 4) are useful when you need custom data formats shared between specific applications. The empty record type (TNF 0) serves as a placeholder in multi-record messages.

NFC Tag Type Comparison
TypeStandardMemorySpeedKey Features
Type 1ISO/IEC 14443-3A96 bytes - 2 KB106 kbit/sNo anti-collision, rewritable
Type 2ISO/IEC 14443-3A48 bytes - 2 KB106 kbit/sRewritable, configurable read-only
Type 3JIS X 6319-4 (FeliCa)2 KB212/424 kbit/sPreconfigured read-only/rewritable
Type 4ISO/IEC 14443-4 A/BUp to 32 KB106/212/424 kbit/sVariable memory, ISO-DEP support
Type 5ISO/IEC 15693Up to 64 KB26.48 kbit/sLong range RFID compatible

Core Web NFC API Interfaces

The Web NFC API provides three primary interfaces that form the foundation of NFC interactions in web applications.

NDEFReader Interface

The NDEFReader interface enables reading and writing NDEF messages from compatible NFC tags. This interface extends EventTarget and provides methods for initiating scans, writing data, and making tags permanently read-only.

Key Methods:

  • scan(options): Initiates NFC polling and returns a Promise
  • write(message, options): Queues data for writing to the next NFC tag
  • makeReadOnly(options): Permanently locks an NFC tag

Event Handlers:

  • onreading: Called when an NFC tag comes within range
  • onreadingerror: Called when an error occurs during reading
// NDEFReader instantiation and basic setup
const ndef = new NDEFReader();

// Set up reading event handler
ndef.onreading = (event) => {
 console.log(`Tag detected: ${event.serialNumber}`);
 for (const record of event.message.records) {
 console.log(`Record type: ${record.recordType}`);
 }
};

// Handle errors
ndef.onreadingerror = (error) => {
 console.log(`NFC error: ${error.message}`);
};

NDEFMessage Interface

The NDEFMessage interface represents NDEF messages received from or sent to NFC tags. This interface exposes a frozen array of NDEFRecord objects through its records property, enabling iteration over all records in a message.

NDEFRecord Interface

The NDEFRecord interface represents individual records within NDEF messages:

  • recordType: The type of record (text, url, mime, etc.)
  • mediaType: MIME type for MIME records
  • id: Record identifier
  • data: DataView containing payload bytes
  • encoding and lang: Text encoding and language for text records
  • toRecords(): Parses nested records from payload data
Reading NFC Tags
1const ndef = new NDEFReader();2 3ndef.onreading = (event) => {4 console.log("NDEF message read from tag");5 6 for (const record of event.message.records) {7 console.log(`Record type: ${record.recordType}`);8 console.log(`MIME type: ${record.mediaType}`);9 10 const decoder = new TextDecoder();11 console.log(`Data: ${decoder.decode(record.data)}`);12 }13};14 15ndef.scan().then(() => {16 console.log("Scanning started successfully");17}).catch(error => {18 console.log(`Scan failed: ${error}`);19});

Processing Different Record Types

Processing different record types requires identifying the record type and decoding the payload appropriately:

ndef.onreading = (event) => {
 const decoder = new TextDecoder();

 for (const record of event.message.records) {
 switch (record.recordType) {
 case "text":
 const textDecoder = new TextDecoder(record.encoding);
 console.log(`Text: ${textDecoder.decode(record.data)} (${record.lang})`);
 break;

 case "url":
 console.log(`URL: ${decoder.decode(record.data)}`);
 break;

 case "mime":
 if (record.mediaType === "application/json") {
 const json = JSON.parse(decoder.decode(record.data));
 console.log(`JSON: ${JSON.stringify(json)}`);
 } else if (record.mediaType.startsWith("image/")) {
 const blob = new Blob([record.data], { type: record.mediaType });
 const img = document.createElement("img");
 img.src = URL.createObjectURL(blob);
 document.body.appendChild(img);
 }
 break;
 }
 }
};

Reading a Single Tag

Stop scanning after reading one tag to conserve battery:

function readOnce() {
 return new Promise((resolve, reject) => {
 const controller = new AbortController();
 controller.signal.onabort = reject;

 ndef.addEventListener("reading", (event) => {
 controller.abort();
 resolve(event);
 }, { once: true });

 ndef.scan({ signal: controller.signal }).catch(reject);
 });
}

This pattern uses AbortController to automatically stop scanning once a tag is read, which is essential for battery-efficient mobile implementations.

Writing to NFC Tags

Writing NFC tags enables applications to program physical objects with digital content, from simple text messages to complex structured data.

Basic Writing Operations

const ndef = new NDEFReader();

// Writing a simple text message
ndef.write("Hello World").then(() => {
 console.log("Text message written successfully");
});

// Writing a URL with explicit record type
ndef.write({
 records: [{ recordType: "url", data: "https://example.com/" }]
}).then(() => {
 console.log("URL written successfully");
});

Writing Structured Data

const ndef = new NDEFReader();
const encoder = new TextEncoder();

ndef.write({
 records: [
 { recordType: "url", data: "https://example.com/page" },
 { recordType: "text", data: "Example Page", lang: "en" },
 {
 recordType: "mime",
 mediaType: "application/json",
 data: encoder.encode(JSON.stringify({ id: 42, timestamp: Date.now() }))
 }
 ]
}).then(() => {
 console.log("Multi-record message written");
});

Writing Smart Posters

const ndef = new NDEFReader();
const encoder = new TextEncoder();

ndef.write({
 records: [{
 recordType: "smart-poster",
 data: {
 records: [
 { recordType: "url", data: "https://example.com/content/19911" },
 { recordType: "text", data: "Content Title" },
 { recordType: ":t", data: encoder.encode("video/mp4") },
 { recordType: ":s", data: new Uint32Array([4096]) },
 { recordType: ":act", data: new Uint8Array([0]) }
 ]
 }
 }]
});

Smart poster records provide a comprehensive format for sharing web content, including URL, title, media type, size, and desired action when scanned.

Making Tags Permanently Read-Only

The makeReadOnly() method permanently locks NFC tags against future modifications, which is essential for applications where tag content should remain unchanged after initial programming. This operation is irreversible and should be used carefully.

const ndef = new NDEFReader();

// Make a tag read-only after writing content
ndef.write("Permanent content").then(async () => {
 console.log("Content written");
 await ndef.makeReadOnly();
 console.log("Tag is now permanently read-only");
});

// Make read-only directly
ndef.makeReadOnly().then(() => {
 console.log("Tag made permanently read-only");
});

The makeReadOnly operation follows similar timing patterns to write operations, requiring the tag to be scanned and verified before the lock is applied. Once locked, no further writes or makeReadOnly operations can modify the tag. This permanence makes it ideal for ticketing, authentication, and product labeling applications where content integrity is critical.

Important considerations:

  • Test makeReadOnly operations on your target tag types before deployment
  • Some tags may have manufacturer-specific lock mechanisms that persist beyond NDEF locking
  • Always verify the lock succeeded by attempting to write after the operation
Feature Detection
1function isWebNFCAvailable() {2 return "NDEFReader" in window;3}4 5if (isWebNFCAvailable()) {6 // Web NFC is available7 const ndef = new NDEFReader();8 // Proceed with NFC operations9} else {10 // Provide alternative experience11 alert("Please use a compatible browser with NFC support");12}

Security Requirements

Secure Context (HTTPS)

The Web NFC API requires a secure context (HTTPS) to prevent unauthorized access to NFC functionality. This requirement ensures that NFC interactions are encrypted and authenticated, protecting users from potential attacks. Development over HTTP is possible on localhost for testing, but production deployments must use HTTPS.

Permission Model

Web NFC is classified as a powerful feature requiring user permission before use. The permission model varies by browser but typically involves a prompt when the page first attempts NFC operations. Users must explicitly grant permission for NFC access, and this permission can be revoked through browser settings.

Visibility-Based Access

NFC operations only occur when the page is visible, preventing background websites from accessing NFC data without user awareness. This provides an additional layer of privacy protection and ensures users know when NFC interactions are happening.

Protecting Users

These security measures work together to protect users in several ways:

  • HTTPS encryption prevents eavesdropping on NFC commands
  • User permission ensures explicit consent before any NFC access
  • Visibility requirement prevents covert NFC scanning in background tabs
  • Secure context requirement blocks NFC access from insecure iframes

Developers should communicate these protections to users, explaining that NFC access requires their explicit permission and that the website cannot access NFC when hidden or running over insecure connections. Our web development team follows these security best practices for all client projects.

Practical Use Cases

Web NFC enables innovative applications across multiple industries

Interactive Marketing

NFC tags in product packaging and displays provide instant access to digital content, promotional offers, and product information without app installation.

Event Ticketing

Digital tickets on NFC-enabled passes can be scanned using web applications for seamless check-in without dedicated hardware.

Product Authentication

NFC tags embedded in products enable verification of authenticity, origin tracking, and supply chain transparency.

Gaming & Entertainment

Mobile games can use NFC tags for physical gameplay elements, unlocking content, and sharing progress through physical interactions.

Best Practices and Performance Considerations

Optimizing Tag Reading Performance

Efficient NFC implementation minimizes battery consumption while providing responsive experiences. Stop scanning after reading the required information:

function readForDuration(durationMs) {
 return new Promise((resolve) => {
 const controller = new AbortController();

 ndef.addEventListener("reading", (event) => {
 resolve(event);
 controller.abort();
 }, { once: true });

 setTimeout(() => controller.abort(), durationMs);
 ndef.scan({ signal: controller.signal });
 });
}

Error Handling

ndef.onreadingerror = (event) => {
 console.log("Error reading NFC tag. Try a different tag.");
};

ndef.scan().then(() => {
 console.log("Ready to scan");
}).catch(error => {
 if (error.name === "NotAllowedError") {
 console.log("NFC permission denied");
 } else if (error.name === "NotSupportedError") {
 console.log("NFC not supported on this device");
 }
});

User Experience Design

  • Provide clear instructions for tapping NFC tags before scanning begins
  • Include visual and haptic feedback for successful reads when possible
  • Handle errors gracefully with actionable messages (e.g., "Try a different tag")
  • Consider timing out scans to prevent battery drain on mobile devices
  • Test with actual target tag types, as performance varies by hardware

Tag Programming Best Practices

When programming NFC tags for your applications, consider these guidelines:

  • Use URL records with appropriate compression to maximize stored information
  • Specify language tags for text records to ensure proper display across locales
  • For complex data, use JSON-encoded MIME records with consistent versioning
  • Test write operations on the exact tag hardware you'll deploy in production
  • Document your tag data format for future maintenance and compatibility

Frequently Asked Questions

Conclusion

The Web NFC API represents a significant capability for modern web applications, enabling direct interaction with NFC tags without requiring native applications. This technology bridges the physical and digital worlds, creating opportunities for innovative user experiences across retail, events, gaming, and beyond.

While current browser support is limited primarily to Chromium-based browsers on Android, the specification continues to mature and may see broader adoption as the web platform evolves. Developers implementing Web NFC should use feature detection, provide appropriate fallbacks, and focus on use cases where the technology provides clear advantages over alternatives like QR codes or native apps.

The combination of secure context requirements, explicit user permission, and visibility-based operation ensures that Web NFC provides strong security and privacy protections. These safeguards make it suitable for sensitive applications like ticketing and authentication.

Understanding NDEF format, core interfaces, and operational patterns enables developers to build robust NFC-enabled applications that enhance user engagement through seamless physical-digital interactions. When combined with our web development services, Web NFC enables creating innovative contactless experiences that set your applications apart. Our AI automation expertise can also help integrate NFC with intelligent workflows for enhanced business automation.


Sources:

  1. MDN Web Docs - Web NFC API
  2. W3C Web NFC Specification
  3. WebNfc.org - Introduction

Ready to Build NFC-Enabled Web Applications?

Our team of web development experts can help you implement Web NFC technology and create innovative contactless experiences for your users.