Web Nfc
Web NFC reads and writes NDEF tags using an NDEFReader. The serial number alone is enough to build location-aware unlocks and treasure hunts. Writing adds a URL or text payload to a physical tag. Chrome on Android only.
Most developers think NFC is payment infrastructure. Tap your card, transaction clears, done. The Web NFC API has nothing to do with payments.
It is about tags. Small passive chips embedded in stickers, cards, wristbands, and museum exhibits. When you bring your phone close enough, the tag announces itself. The Web NFC API lets JavaScript respond.
The Range and the Protocol
NFC (Near Field Communication) works at distances under 10 centimeters -- close enough to be intentional. The Web NFC API is limited to a specific subset of the NFC protocol called NDEF: NFC Data Exchange Format. It is the simplest, most interoperable NFC profile.
NDEF handles reading and writing structured data records to passive tags. It does not give you low-level I/O, the ability to execute code on a tag, or access to non-NDEF tag types. It is the approachable, interoperable surface.
Reading a Tag
const reader = new NDEFReader()
reader.addEventListener('reading', ({ serialNumber, message }) => {
console.log('Tag serial:', serialNumber)
for (const record of message.records) {
console.log('Record type:', record.recordType)
if (record.recordType === 'text') {
const decoder = new TextDecoder(record.encoding)
console.log('Text:', decoder.decode(record.data))
}
}
})
reader.addEventListener('readingerror', () => {
console.log('Tag read failed -- try again')
})
await reader.scan() // must call from a user gesturereader.scan() activates the NFC scanner. From that point, every time the user brings a compatible tag close to the device, the reading event fires.
event.serialNumber is a globally unique ID. Every NFC tag has one, assigned at manufacture. This is the minimum useful data from any tag -- even if the tag has no NDEF records, its serial number can identify it. This is enough to build:
- A treasure hunt where locations are tagged
- A museum where tapping near an exhibit triggers audio or text
- An unlock mechanism where specific tags activate specific features
Writing a Tag
const reader = new NDEFReader()
await reader.write({
records: [
{ recordType: 'url', data: 'https://example.com/tag-activated' },
]
})write() waits for the user to bring a writable tag close to the device, then writes the NDEF message. The records array contains one or more NDEF records. Common record types:
'text'-- plain text content'url'-- a URL, often used to launch a website when tapped on an Android device
Not all tags are writable. Write-protected tags will throw. Some tags are one-time-write -- once written, they are permanently locked.
ExpandWeb NFC: NDEFReader read flow with serial number and NDEF records, and the write flow with record types
What You Cannot Read from an AirTag
Apple AirTags have an NFC chip. The serial number is readable by any NFC-capable device. That is all. Apple encrypts the owner information and the tag's active data behind their own security layer. A Web NFC scan of an AirTag returns the serial number and nothing else.
This is deliberate -- if you could read arbitrary data from an AirTag, you could track people without their knowledge. The serial number alone is not enough to de-anonymize a tag without access to Apple's registry.
For third-party NFC stickers and cards (which cost a few cents each), you have full read/write access to the NDEF data.
The Permission Model
Web NFC requires both permission and a user gesture. On the first scan() or write() call, the browser shows a permission dialog. On Android, the OS also handles NFC proximity detection -- scan() does not drain the battery by actively polling; it registers with the OS to be notified.
Support
Web NFC is experimental and Android-only. It requires Chrome on Android. Safari on iOS does not support Web NFC. No desktop browser supports it (desktop hardware generally lacks NFC readers).
The only practical way to use Web NFC is to publish your site over HTTPS and test on an Android device with Chrome.
if ('NDEFReader' in window) {
// Web NFC is available
}That closes out the external-device chapter. The next chapter is about the device itself reporting state -- starting with the simplest possible feedback mechanism: making the phone buzz.
The Essentials
- Web NFC is limited to NDEF tags -- the interoperable read/write NFC profile. No low-level I/O, no code execution on tags.
event.serialNumberis globally unique and available on every tag -- even with no NDEF records. A serial number alone is enough to build location-aware features.reader.scan()activates scanning.reader.write(message)writes NDEF records on the next tag presented. Both require a user gesture.- Record types:
'text'for plain text,'url'for links. More types exist in the spec for other payloads. - Chrome on Android only. iOS does not support Web NFC. Desktop browsers have no NFC hardware.
Further Reading and Watching
- Reading NFC from JavaScript demo (YouTube) -- live demo of NDEFReader.scan() reading a real NFC tag, showing serialNumber and message records in the browser
- Interact with NFC devices on Chrome for Android -- Chrome for Developers -- official guide covering permissions, record types, write operations, and error handling