Web NFC is a browser API that lets a web page read and write NFC tags, using the NDEF message format, through the NDEFReader interface. NFC stands for Near Field Communication, wireless contact at a distance of a few centimeters on 13.56 MHz. Web NFC is a W3C Community Group draft that its own text calls unstable, and it works only in secure contexts.
The entry point is the NDEFReader class. Feature detection is "NDEFReader" in window, and the spec warns that a true result does not prove NFC hardware exists. The API is a default powerful feature with the permission name "nfc", so the browser asks the user before scanning or writing.
NDEF stands for NFC Forum Data Exchange Format, a small binary message format. A message holds a list of records. In JavaScript each NDEFRecord exposes recordType, mediaType, id, encoding, lang and data. The common recordType values are "text", "url", "mime", "smart-poster" and "empty". The data property is a DataView, so you decode text with TextDecoder.
The methods map to the three jobs:
An NFC reader works by polling, and the spec points out a side effect. If you call write() or makeReadOnly() without a running scan(), the browser polls just long enough to find the tag, reads it first, and then performs the write. If scan() is already running with a reading listener, that listener fires once during the write too.
The scope is limited to NDEF. Low-level operations such as ISO-DEP and NFC-A/B/F, plus card emulation, are out of scope, and peer-to-peer is not supported. The sample below runs in Node with a simulated message shaped like a real one, because Node has no NFC.
const enc = new TextEncoder();
const bytes = enc.encode("Hello World");
const message = { records: [
{ recordType: "text", encoding: "utf-8", lang: "en", data: new DataView(bytes.buffer) },
{ recordType: "url", data: new DataView(enc.encode("https://example.com/").buffer) },
{ recordType: "empty" },
] };
for (const record of message.records) {
switch (record.recordType) {
case "text": console.log(`Text: ${new TextDecoder(record.encoding).decode(record.data)} (${record.lang})`); break;
case "url": console.log(`URL: ${new TextDecoder().decode(record.data)}`); break;
default: console.log("Record type:", record.recordType);
}
}
console.log("supported check:", "NDEFReader" in globalThis);
Output:
Text: Hello World (en)
URL: https://example.com/
Record type: empty
supported check: false
Web NFC is available in Chrome on Android 89 and later. MDN compatibility data shows no support in desktop Chrome, Firefox or Safari, and marks NDEFReader as experimental. A page on an iPhone or a laptop cannot read tags with it, so offer a QR code or manual entry as the fallback.