Web NFC

Draft Community Group Report

Latest editor's draft:
https://w3c.github.io/web-nfc/
Editors:
Kenneth Rohde Christiansen ( Intel )
Zoltan Kis ( Intel )
François Beaufort ( Google LLC )
Former editor:
Alexander Shalamov ( Intel )
Participate:
GitHub w3c/web-nfc
File a bug
Commit history
Pull requests

Abstract

Near Field Communication (NFC) enables wireless communication between two devices at close proximity, usually less than a few centimeters. NFC is an international standard (ISO/IEC 18092) defining an interface and protocol for simple wireless interconnection of closely coupled devices operating at 13.56 MHz. The hardware standard is defined in NFC Forum Technical Specifications .

This document defines an API to enable selected use-cases based on NFC technology. The current scope of the specification is NDEF . Other NFC technologies may be supported in the future.

Status of This Document

This is a preview

Do not attempt to implement this version of the specification. Do not reference this version as authoritative in any way. Instead, see https://w3c.github.io/web-nfc/ for the Editor's draft.

This specification was published by the Web NFC Community Group . It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups .

Implementers need to be aware that this specification is considered unstable. Implementers who are not taking part in the discussions will find the specification changing out from under them in incompatible ways. Vendors interested in implementing this specification before it eventually reaches the Candidate Recommendation phase should subscribe to the repository on GitHub and take part in the discussions.

1. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY , MUST , MUST NOT , SHOULD , and SHOULD NOT in this document are to be interpreted as described in BCP 14 [ RFC2119 ] [ RFC8174 ] when, and only when, they appear in all capitals, as shown here.

This document defines conformance criteria that apply to a single product: the UA (user agent) that implements the interfaces it contains.

2. Introduction

This section is non-normative.

NFC user scenarios can be grouped as follows:

NFC works using magnetic induction, meaning that the reader (an active, powered device) will emit a small electric charge which then creates a magnetic field. This field powers the passive device which turns it into electrical impulses to communicate data. Thus, when the devices are within range, a read is always performed (see NFC Analog Specification and NFC Digital Protocol, NFC Forum, 2006). The peer-to-peer connection works in a similar way, as the device periodically switches into a so-called initiator mode in order to scan for targets, then later to fall back into target mode. If a target is found, the data is read the same way as for tags.

As NFC is based on existing RFID standards, many NFC chipsets support reading RFID tags, but some of these are only supported by single vendors and not part of the NFC standards. As such, this document specifies ways to interact with the NFC Data Exchange Format (NDEF).

3. Terminology and conventions

The Augmented Backus-Naur Form (ABNF) notation used is specified in [ RFC5234 ].

3.2 NFC specific terms

NFC stands for Near Field Communications, a short-range wireless technology operating at 13.56 MHz which enables communication between devices at a distance less than 10 cm. The NFC communications protocols and data exchange formats, and are based on existing radio-frequency identification (RFID) standards, including ISO/IEC 14443 and FeliCa. The NFC standards include ISO/IEC 18092[5] and those defined by the NFC Forum. See NFC Forum Technical Specifications for a complete listing.

An NFC adapter is the software entity in the underlying platform which provides access to NFC functionality implemented in a given hardware element (NFC chip). A device may have multiple NFC adapters, for instance a built-in one, and one or more attached via USB.

An NFC tag is a passive NFC device. The NFC tag is powered by magnetic induction when an active NFC device is in proximity range. An NFC tag contains a single NDEF message .

Note

The way of reading the message may happen through proprietary technologies, which require the reader and the tag to be of the same manufacturer. Implementations are expected to encapsulate this.

An NFC peer is an active, powered device, which can interact with other devices in order to exchange data using NFC.

An NFC device is either an NFC peer , or an NFC tag .

NDEF is an abbreviation for NFC Forum Data Exchange Format, a lightweight binary message format that is standardized in [ NFC-NDEF ].

An NDEF message encapsulates one or more application-defined NDEF record s. NDEF messages can be stored on an NFC tag or exchanged between NFC-enabled devices.

The term NFC content denotes all bytes sent to or received from an NFC tag or an NFC peer . In the current API it is synonym to NDEF message .

4. The NFC Standard

This section is non-normative.

NFC is standardized in the NFC Forum and described in [ NFC-STANDARDS ].

4.1 NDEF compatible tag types

This section is non-normative.

The NFC Forum has mandated the support of five different tag types to be operable with NFC devices. The same is required on operating systems, such as Android.

In addition to that, the MIFARE Standard specifies a way for NDEF to work on top of the older MIFARE Standard , which may be optionally supported by implementers.

A note about the NDEF mapping can be found here: MIFARE Classic as NFC Type MIFARE Classic Tag

  1. NFC Forum Type 1 : This tag is based on the ISO/IEC 14443-3A (NFC-A). The tags are rewritable and can be configured to become read-only. Memory size can be between 96 bytes and 2 Kbytes. Communication speed is 106 kbit/sec. In contrast to all other types, these tags have no anti-collision protection for dealing with multiple tags within the NFC field.
  2. NFC Forum Type 2 : This tag is based on the ISO/IEC 14443-3A (NFC-A). The tags are rewritable and can be configured to become read-only. Memory size can be between 48 bytes and 2 Kbytes. Communication speed is 106 kbit/sec.
  3. NFC Forum Type 3 : This tag is based on the Japanese Industrial Standard (JIS) X 6319-4 (ISO/IEC 18092), commonly known as FeliCa. The tags are preconfigured to be either rewritable or read-only. Memory is 2 kbytes. Communication speed is 212 kbit/sec or 424 kbit/s.
  4. NFC Forum Type 4 : This tag is based on the ISO/IEC 14443-4 A/B (NFC A, NFC B) and thus supports either NFC-A or NFC-B for communication. On top of that the tag may optionally support ISO-DEP (Data Exchange Protocol defined in ISO/IEC 14443 (ISO/IEC 14443-4:2008 Part 4: Transmission protocol). The tags are preconfigured to be either rewritable or read-only. Variable memory, up to 32 kbytes. Supports three different communication speeds 106 or 212 or 424 kbit/s.
  5. NFC Forum Type 5 : This tag is based on ISO/IEC 15693 (NFC-V) and allows reading and writing an NDEF message on a ISO/IEC 15693 RF tag that is accessible by long range RFID readers as well. The NFC communication is limited to short distance and may use the Active Communication Mode of ISO/IEC 18092 where the sending peer generates the field which balances power consumption and improves link stability. Variable memory, up to 64 kbytes. Communication speed 26.48 kbit/s
  6. MIFARE Standard : This tag, often sold under the brand names MIFARE Classic or MIFARE Mini, is based on the ISO/IEC 14443-3A (also known as NFC-A, as defined in ISO/IEC 14443-3:2011, Part 3: Initialization and anticollision). The tags are rewritable and can be configured to become read-only. Memory size can be between 320 and 4 kbytes. Communication speed is 106 kbit/sec.
    Note

    MIFARE Standard is a not an NFC Forum type and can only be read by devices using NXP hardware. Support for reading and writing to tags based on the MIFARE Standard is thus non-nominative, but the type is included due to the popularity and use in legacy systems.

In addition to data types standardized for NDEF record s by the NFC Forum, many commercial products such as bus cards, door openers may be based on the MIFARE Standard which requires specific NFC chips (same vendor of card and reader) in order to function.

Card emulation mode capabilities also depend on the NFC chip in the device. For payments, a Secure Element is often needed.

4.2 The NDEF record and fields

An NDEF record is a part of an NDEF message . Each record is a binary structure that contains a data payload, as well as associated type information. In addition to this, it includes information about how the data is structured, like payload size, whether the data is chunked over multiple records etc.

A generic record looks like the following:

Only the first three bytes (lines in figure) are mandatory. First the header byte, followed by the TYPE LENGTH field and PAYLOAD LENGTH field , which may both be zero.

The TNF field (bit 0-2 , type name format) indicates the format of the type name and is often exposed by native NFC software stacks. The field can take binary values denoting the following NDEF record payload types:
TNF value Description
0 Empty record
1 NFC Forum well-known type record
2 MIME type record
3 Absolute-URL record
4 NFC Forum external type record
5 Unknown record
6 Unchanged record
7 Reserved for future use

The IL field (bit 3 , id length) indicates whether an ID LENGTH field is present. If the IL field is 0 , then the ID field is not present either.

The SR field (bit 4 , short record) indicates a short record, one with a payload length <= 255 bytes. Normal records can have payload lengths exceeding 255 bytes up to a maximum of 4 GB. Short records only use one byte to indicate length, whether as normal records use 4 bytes ( 2 32 -1 bytes).

The CF field (bit 5 , chunk flag) indicates whether the payload is chunked across multiple records.

Note

Web NFC turns all received chunked records into logical records and transparently chunks sent payload when that is needed.

The ME field (bit 6 , message end) indicates whether this record is the last in the NDEF message .

The MB field (bit 7 , message begin) indicates whether this record is the first of the NDEF message .

The TYPE LENGTH field is an unsigned 8-bit integer that denotes the byte size of the TYPE field .

The TYPE field is a globally unique and maintained identifier that describes the type of the PAYLOAD field in a structure, encoding and format dictated by value of the TNF field .

Note

The NFC Record Type Definition (RTD) Technical Specification requires that the TYPE field names MUST be compared in case-insensitive manner.

The ID LENGTH field is an unsigned 8-bit integer that denotes the byte size of the ID field .

The ID field is an identifier in the form of a URI reference ([ RFC3986 ]) that is unique, and can be absolute of relative (in the latter case the application must provide a base URI). Middle and terminating chunk records MUST NOT have an ID field , other records MAY have it.

The PAYLOAD LENGTH field denotes the byte size of the PAYLOAD field . If the SR field is 1 , its size is one byte, otherwise 4 bytes, representing an 8-bit or 32-bit unsigned integer, respectively.

The PAYLOAD field carries the application bytes. Any internal structure of the data is opaque to NDEF. Note that in certain cases discussed later, this field MAY contain an NDEF message as data.

4.3 NDEF Record types

4.3.1 Empty NDEF record (TNF 0)

An empty record 's' TYPE LENGTH field , ID LENGTH field and PAYLOAD LENGTH field MUST be 0 , thus the TYPE field , ID field and PAYLOAD field MUST NOT be present.

4.3.2 Well-known type records (TNF 1)

The NFC Forum has standardized a small set of useful sub record types in [ NFC-RTD ] (Resource Type Definition specifications) called well-known type s, for instance text, URL, media and opaque binary data. In addition, there are record types designed for more complex interactions, such as smart posters (containing optional embedded records for url, text, signature and actions), and handover records.

These sub record types can be stored in the well-known type record .

The type information stored in the TYPE field can be of two kinds:
  • NFC Forum global type that are defined and managed by the NFC Forum and usually start with uppercase letter. Examples: " T " for text, " U " for URL, " Sp " for smart poster, " Sig " for signature, " Hc " for handover carrier, " Hr " for handover request, " Hs " for handover select, etc.
  • NFC Forum local type that are defined by the NFC Forum or by an application, and always start with lowercase letter or a number. Those are usually short strings that are unique only within the local context of the containing record. They are used when types meaning doesn't matter outside of the local context of the containing record and when storage usage is a hard constraint. See Smart poster for an example on how local types are used.

    Note

    A local type is thus defined in terms of a containing record type, and thus doesn't need any namespacing. For this reason the same local type name can be used within another record type with different meaning and different payload type.

4.3.2.1 Text record
The Text record is a well-known type record that is defined in the [ NDEF-TEXT ] specification. The TNF field is 1 and the TYPE field is " T " ( 0x54 ). The first byte of the PAYLOAD field is a status byte, followed by the language tag in US-ASCII encoding. The rest of the payload is the actual text, encoded either in UTF-8 or UTF-16, as indicated by the status byte as follows:
  • Bits 0 to 5 define the length of the language tag .
  • Bit 6 is 0 .
  • If bit 7 if set, means the payload is encoded in UTF-8, otherwise in UTF-16.
4.3.2.2 URI record

URI record is defined in [ NDEF-URI ]. The TNF field is 1 and the TYPE field is " U " ( 0x55 ). The first byte of the PAYLOAD field is a URI identifier code, in fact an index in an abbreviation table where the values are prepended to the rest of the URI. For instance the value 0 denotes no prepending, 1 denotes " http://www. ", 0x04 denotes " https:// "" and so on. The rest of the payload contains the rest of the URI as a UTF-8 string (and if the first byte is 0 , then it denotes the whole URI).

The URI is defined in [ RFC3987 ] and in fact is a UTF-8 encoded IRI that can be a URN or a URL.

4.3.2.3 Smart poster record

Smart poster is defined in [ NDEF-SMARTPOSTER ] as an NDEF record that contains an NDEF message as payload, which may contain several records: a mandatory URI record that refers to a content, and additional optional records related to the content: a title record (a Text record ), one or more icon records, a type record, a size record and an action record.

Icon records are MIME type record s. If multiple icon records are included, readers SHOULD select only one of them to display.

The type record has local type name " t " specific to smart poster and the PAYLOAD field contains a UTF-8 encoded MIME type for the content referred to by the URI record.

The size record has local type name " s " specific to smart poster and the PAYLOAD field contains a 4-byte 32 bit unsigned integer that denotes the size of the object referred to by the URL in the URI record.

The action record has local type name " act " specific to smart poster and the PAYLOAD field contains a single byte, whose value has the following meaning:

Value Description
0 Do the action
1 Save for later
2 Open for editing
3..0xFF Reserved for future use

The action record is optional and there is no default action on the smart poster content if the action record is missing.

Note

At the time of NDEF standardization the value 0 ("do the action") was meant for use cases like send an SMS, make a call or launch browser. Similarly, the value 1 , ("save the content for later processing") was meant for use cases like store the SMS in inbox, save the URL in bookmarks, or save the phone number to contacts. Also, the value 2 ("open for editing") was meant to open the smart poster content with a default application for editing.

Implementations don't need to implement any standardized behavior for the actions defined here. In this API it's up to the applications what actions they define (that may include the use cases above). However, Web NFC just provides the values.

The example below shows a smart poster record that embeds a text and a URL record.
4.3.2.4 Signature records

NDEF Signature is defined [ NDEF-SIGNATURE ]. Its TYPE field contains " Sig " ( 0x53 , 0x69 , 0x67 ) and its PAYLOAD field contains version, signature and a certificate chain. In this version of the API, Web NFC only provides the raw byte content of the payload (see this issue ).

4.3.2.5 Handover records

NFC handover is defined [ NFC-HANDOVER ] and the corresponding message structure that allows negotiation and activation of an alternative communication carrier, such as Bluetooth or WiFi. The negotiated communication carrier would then be used (separately) to perform certain activities between the two devices, such as sending photos to the other device, printing to a Bluetooth printer or streaming video to a television set. Web NFC does not support this at the moment (see this issue .

4.3.3 MIME type records (TNF 2)

The MIME type record s are records that store binary data with associated MIME type .

4.3.4 Absolute-URL records (TNF 3)

In absolute-URL record s the TYPE field contains the absolute-URL string , and not the payload.

Note

NOTE: Some platforms, like Windows Phone have stored additional data in the payload, but any payload data in these records are ignored by other platforms such as Android. On Android, reading such a record, will attempt to load the URL in Chrome and it is as such not intended for client applications.

4.3.5 External type records (TNF 4)

The NFC Forum external type record s are for application specified data types and are defined in NFC Record Type Definition (RTD) Technical Specification .

The external type is a URN with the prefix "urn:nfc:ext:" followed by the name of the owner domain, adding a colon, then a non-zero type name, for instance "urn:nfc:ext:w3.org:atype" , stored as "w3.org:atype" in the TYPE field .

4.3.6 Unknown type records (TNF 5)

The unknown record s are records that store opaque data without associated MIME type , meaning that the application/octet-stream default MIME type MAY be assumed. The [ NFC-NDEF ] specification recommends that NDEF parsers store or forward the payload without processing it.

4.3.7 Unchanged type records (TNF 6)

The unchanged record s are record chunks of a chunked data set, and is used for any, but the first record. A chunked payload is spread across multiple NDEF record s that undergo the following rules:
  • The initial chunk record has the CF field set, its TYPE field set to the type of the whole chunked payload and its ID field MAY be set to an identifier used for the whole chunked payload. Its PAYLOAD LENGTH field denotes the size of the payload chunk in this record only.
  • The middle chunk records have the CF field set, have the same ID field as the first chunk, their TYPE LENGTH field and IL field MUST be 0 and their TNF field MUST be 6 (unchanged).
  • The terminating chunk record has this flag cleared, and in rest undergo the same rules as the middle chunk records.
  • A chunked payload MUST be contained in a single NDEF message , therefore the initial and middle chunk records cannot have the ME field set.

First record:
Intermediate record:
Last record:

Any implementation of Web NFC MUST transparently expose chunked records as single logical records.

5. Use Cases

This section is non-normative.

A few Web NFC user scenarios are described in the Use Cases document. These user scenarios can be grouped by criteria based on security, privacy and feature categories, resulting in generic flows as follows.

5.1 Reading an NFC tag

  1. Reading an NFC tag containing an NDEF message , when the Document of the top-level browsing context using Web NFC is visible . For instance, a web page instructs the user to tap an NFC tag, and then receives information from the tag.
  2. Reading an NFC tag containing other than NDEF message , when the Document of the top-level browsing context using Web NFC is visible .
  3. Reading an NFC tag when no Document using Web NFC is visible .
    Note

    This use case is not supported in this version of the specification.

5.2 Writing to an NFC tag

The user opens a web page which can write an NFC tag . The write operations may be one of the following:

  1. Writing to an empty NFC tag .
  2. Writing to an NFC tag which already contains a NDEF message with a different record identifier (i.e. overwriting a web-specific tag).
  3. Writing to an NFC tag which already contains a NDEF message with the same record identifier (i.e. updating own tag).
  4. Writing to other, writable NFC tag s (i.e. overwriting a generic tag).

Note

Note that an NFC write operation to an NFC tag always involves also a read operation.

5.3 Pushing data to an NFC peer device

In general, pushing data to another NFC capable device requires that on the initiating device the user would first have to navigate to a web site. The user would then touch the device against another Web NFC equipped device, and data transfer would occur.

On the receiving device the UA will dispatch the content to an application registered and eligible to handle the content, and if that application is a browser which has a Document of the top-level browsing context visible with active NDEFReader , then the content is delivered to the page through the NDEFReadingEvent .

5.4 Handover to another wireless connection type

NFC supports handover protocols to Bluetooth or WiFi connectivity for the purpose of larger volume data transfer. The user touches another NFC capable device, and as a result configuration data is sent for a new Bluetooth or WiFi connection, which is then established between the devices.

Note

This use case is not supported in this version of the specification.

5.5 Payment scenarios

Payment scenarios with Web NFC generally do not refer to supporting the payment process itself, but associating the payment status with a web page in order to have secondary actions. For instance, the user buys goods in a store, and payment options include contactless payment using NFC technology. In general, touching the device to the point of sales terminal receiver area will result in a transaction between the secure element from the device and the point of sales terminal. With Web NFC, if the user navigates to a web site before paying, there may be interaction with that site regarding the payment, e.g. the user could get points and discounts, or get delivered application or service specific data (e.g. tickets, keys, etc) to the device.

Note

This use case is not supported in this version of the specification.

5.6 Support for multiple NFC adapters

Users may attach one or more external NFC adapter s to their devices, in addition to a built-in adapter. Users may use either NFC adapter .

6. Features

This section is non-normative.

High level features for the Web NFC specification include the following:

  1. Support devices with single or multiple NFC adapter s. If there are multiple adapters present when invoking an NFC function then the UA operates all NFC adapter s in parallel.
  2. Support communication with active (powered devices such as readers, phones) and passive (smart cards, tags, etc) devices.
  3. Allow users to act on (e.g. read, write or transceive) discovered NFC devices (passive and active), as well as access the payload which were read in the process as NDEF message s.
  4. Allow users to write a payload via NDEF record s to compatible devices, such as writable tags, when they come in range, as NDEF message s.
  5. [future] Allow manual connection for various technologies such as NFC-A and NFC-F depending on the secondary device.
  6. [future] Allow NFC handover to Bluetooth or WiFi.
  7. [future] Allow card emulation with secure element or host card emulation.

This specification makes a few simplifications in what use cases and data types Web NFC can handle:

7. Examples

This section is non-normative.

This section shows how developers can make use of the various features of this specification.

7.1 Push a text string to either a tag or peer

Pushing a text string to any kind of device is straightforward. Options can be left out, as they default to pushing to both tags and peers.

const writer = new NDEFWriter();
writer.push(
  "Hello World"
).then(() => {
  console.log("Message pushed.");
}).catch(error => {
  console.log(`Push failed :-( try again: ${error}.`);
});

7.2 Push a text string to a peer device

It is possible to restrict to which devices (tags or peers) data should be pushed. Below push is specified only to peers, and thus, no data is pushed when the user taps a tag.

const writer = new NDEFWriter();
writer.push(
  "Text meant for peers only", { target: "peer" }
).then(() => {
  console.log("Message pushed.");
}).catch(_ => {
  console.log("Push failed :-( try again.");
});

7.3 Push a URL to either a tag or peer

In order to push an NDEF record of URL type, simply use NDEFMessage.

const writer = new NDEFWriter();
writer.push({
  records: [{ recordType: "url", data: "https://w3c.github.io/web-nfc/" }]
}).then(() => {
  console.log("Message pushed.");
}).catch(_ => {
  console.log("Push failed :-( try again.");
});

7.4 Read data from tag, and write to empty ones

This example shows reading various different kinds of data which can be stored on a tag. If the tag is unformatted or contains an empty record, a text message is written with the value "Hello World".

const reader = new NDEFReader();
await reader.scan();
reader.onreading = event => {
  const message = event.message;
  if (message.records.length == 0 ||     // unformatted tag
      message.records[0].recordType == 'empty' ) {  // empty record
    const writer = new NDEFWriter();
    writer.push({
      records: [{ recordType: "text", data: 'Hello World' }]
    });
    return;
  }
  const decoder = new TextDecoder();
  for (const record of 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") {
          console.log(`JSON: ${JSON.parse(decoder.decode(record.data))}`);
        }
        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);
          img.onload = () => window.URL.revokeObjectURL(this.src);
          document.body.appendChild(img);
        }
        else {
          console.log(`Media not handled`);
        }
        break;
    }
  }
};

7.5 Save and restore game progress with another device

Filtering of relevant data sources can be done by the use of the NDEFScanOptions . Below we accept the record identifier URL with " /mypath/mygame/ " in its path from " mygame.com " domain and its subdomains. When we read the data, we immediately update the game progress by issuing a push with a custom NDEF data layout.

The example allows reading and pushing to both peers and tags, whichever one is tapped first.

const reader = new NDEFReader();
await reader.scan({ id: "https://mygame.com/mypath/mygame" });
reader.onreading = async event => {
  console.log(`Game state: ${ JSON.stringify(event.message.records) }`);
  const encoder = new TextEncoder();
  const newMessage = {
    records: [{
      id: "/mypath/mygame/update",
      recordType: "mime",
      mediaType: "application/json",
      data: encoder.encode(JSON.stringify({
        level: 3,
        points: 4500,
        lives: 3
      }))
    }]
  };
  const writer = new NDEFWriter();
  await writer.push(newMessage);
  console.log("Pushed message");
};

7.6 Push and read JSON (serialized and deserialized)

Storing and receiving JSON data is easy with serialization and deserialization.

const reader = new NDEFReader();
await reader.scan({
  mediaType: "application/*json"
});
reader.onreading = event => {
  const decoder = new TextDecoder();
  for (const record of event.message.records) {
    if (record.mediaType === 'application/json') {
      const json = JSON.parse(decoder.decode(record.data));
      const article =/^[aeio]/i.test(json.title) ? "an" : "a";
      console.log(`${json.name} is ${article} ${json.title}`);
    }
  }
};
const writer = new NDEFWriter();
const encoder = new TextEncoder();
writer.push({
  records: [
    {
      recordType: "mime",
      mediaType: "application/json",
      data: encoder.encode(JSON.stringify({
        name: "Benny Jensen",
        title: "Banker"
      }))
    },
    {
      recordType: "mime",
      mediaType: "application/json",
      data: encoder.encode(JSON.stringify({
        name: "Zoey Braun",
        title: "Engineer"
      }))
    }]
});

7.7 Write data to tag and print out existing data

Pushing data to a tag requires tapping it. If existing data should be read during the same tap, we need to set the ignoreRead property to false .

const reader = new NDEFReader();
reader.scan().then(() => {
  reader.onreading = event => {
    const decoder = new TextDecoder();
    for (const record of event.message.records) {
      console.log("Record type:  " + record.recordType);
      console.log("MIME type:    " + record.mediaType);
      console.log("=== data ===\n" + decoder.decode(record.data));
    }
  };
  const writer = new NDEFWriter();
  return writer.push("Pushing data is fun!", { target: "tag", ignoreRead: false });
}).catch(error => {
  console.log(`Push failed :-( try again: ${error}.`);
});

7.8 Stop listening to NDEF messages

Read NDEF messages for 3 seconds by using signal .

const reader = new NDEFReader();
const controller = new AbortController();
await reader.scan({ signal: controller.signal });
reader.onreading = event => {
  console.log("NDEF message read.");
};
controller.signal.onabort = event => {
  console.log("We're done waiting for NDEF messages.");
};
// Stop listening to NDEF messages after 3s.
setTimeout(


()

=>

controller.abort(),

3000

);

7.9 Push a smart poster message

const writer = new NDEFWriter();
writer.push({ records: [
  {
    recordType: "smart-poster",
    data: { records: [
      {
        recordType: "url",
        data: "https://my.org/content/19911"
      },
      {
        recordType: "t", // smart poster type, a local type to Sp
        data: "image/gif"
      },
      {
        recordType: "text",
        data: "Funny dance"
      },
      {
        recordType: "s",  // size, a local type to Sp
        data: 4096  // byte size of the content at the URL above
      },
      {
        recordType: "act",  // action, a local type to Sp
        data: 0  // do the action, in this case open in the browser
      }
    ]}
  }
]});

7.10 Read an external record with an NDEF message as payload

External type records can be used to create application defined records. These records may contain an NDEF message as payload, with its own NDEF records , including local types that are used in the context of the application.

Note that the smart poster record type also contains an NDEF message as payload.

As NDEF gives no guarantee on the ordering of records, using an external type record with an NDEF message as payload, can be useful for encapsulating related data.

This example shows how to read an external record for social posts, which contains an NDEF message , containing a text record and a record with the local type "act" (action), with definition borrowed from smart poster , but used in local application context.

const reader = new NDEFReader();
await reader.scan({ recordType: "example.com:sp" });
reader.onreading = event => {
  const socialPost = event.message.records[0];
  if (!socialPost) {
    return;
  }
  let action;
  let text = "";
  const decoder = new TextDecoder();
  for (let record of socialPost.toRecords()) {
    switch (record.recordType) {
      case "text":
        text = decoder.decode(record.data);
        break;
      case "act":
        action = record.data.getUint8(0);
        break;
    }
  }
  switch (action) {
    case 0: // do the action
      console.log(`Post "${text}" to timeline`);
      break;
    case 1: // save for later
      console.log(`Save "${text}" as a draft`);
      break;
    case 2: // open for editing
      console.log(`Show editable post with "${text}"`);
      break;
  }
};

7.11 Push an external record with an NDEF message as payload

External type records can be used to create application defined records that may even contain an NDEF message as payload.

const writer = new NDEFWriter();
writer.push({ records: [
  {
    recordType: "example.game:a",
    data: {
      records: [
        {
          recordType: "url",
          data: "https://example.game/42"
        },
        {
          recordType: "text",
          data: "Game context given here"
        },
        {
          recordType: "mime",
          mediaType: "image/png"
          data: getImageBytes(fromURL);
        }
      ]
    }
  }
]});

7.12 Push and read unknown records inside an external record

Unknown type records may be useful inside external type records as developers know what they represent and therefore can avoid specifying the mime type.

const encoder = new TextEncoder();
const writer = new NDEFWriter();
writer.push({ records: [
  {
    recordType: "example.com:shoppingItem", // External record
    data: {
      records: [
        {
          recordType: "unknown", // Shopping item name
          data: encoder.encode("Food")
        },
        {
          recordType: "unknown", // Shopping item description
          data: encoder.encode("Provide nutritional support for an organism.")
        }
      ]
    }
  }
]});

const reader = new NDEFReader();
await reader.scan({ recordType: "example.com:shoppingItem" });
reader.onreading = event => {
  const shoppingItemRecord = event.message.records[0];
  if (!shoppingItemRecord) {
    return;
  }
  const [nameRecord, descriptionRecord] = shoppingItemRecord.toRecords();
  const decoder = new TextDecoder();
  console.log("Item name: " + decoder.decode(nameRecord.data));
  console.log("Item description: " + decoder.decode(descriptionRecord.data));
};

8. Security and Privacy

The trust model, attacker model, threat model and possible mitigation proposals for Web NFC are presented in the Security and Privacy document. This section presents the chosen security and privacy model through normative requirements to implementations.

8.1 Chain of trust

Web pages using Web NFC are not trusted. This means that the user needs to be aware of exactly what a web page is intending to do with NFC at any given moment. Implementations need to make sure that when the user authorizes a method of this API, then only that action is run, without side effects, and exactly in the context and the number of times the user allows the execution of NFC related operations, according to the algorithmic steps detailed in this specification.

The integrity of NFC content SHOULD NOT be trusted when used for implementing security policies, for instance the authenticity of record identifier , unless a prearranged trust relationship exists.

Security considerations for media types in general are discussed in [ RFC2048 ] and [ RFC2046 ].

8.2 Threats

The main threats are summarized in the Security and Privacy document.

In this specification the following threats are handled with the highest priority:

8.3 Permissions and user prompts

This specification attempts to minimize user prompting and uses implicit security policies to address the threats . However, this specification does not describe, nor does it mandate specific user prompting policies. The term obtain permission is used for acquiring trust for a given operation.

Note

The Permissions API is suggested to be used by UAs for implementing NFC related Permissions in order to minimize the need for user prompting.

All expressed permission s that are preserved beyond the current browsing session MUST be revocable.

8.4 Security policies

This section is non-normative.

This section summarizes the security policies which are specified as normative requirements in the respective algorithms of this specification.

8.4.1 Secure Context

Only secure contexts are allowed to access NFC content . Browsers may ignore this rule for development purposes only.

8.4.2 Visible document

Web NFC functionality is allowed only for the Document of the top-level browsing context , which must be visible .

This also means that UAs should block access to the NFC radio if the display is off or the device is locked. For backgrounded web pages, receiving and pushing NFC content must be suspended .

8.4.3 Permissions controls

Making an NFC tag read-only must obtain permission , or otherwise fail.

Setting up listeners for reading NFC content should obtain permission .

The process of reading an NDEF message does not need to obtain permission .

Pushing NFC content to an NFC peer does not need to obtain permission , but the other rules in this section apply. See the §  10.9 Writing or pushing content section.

Pushing an NDEF message to an NFC tag does not need to obtain permission , if the existing NDEF message only contains NDEF record s without ID field s, or with ID field s matching the registrable domain of the current settings object 's origin. Otherwise the UA must obtain permission for pushing NFC content which overwrites existing information. See also the §  10.9 Writing or pushing content section.

Since all local content that a web page has access to can be shared with NFC, the user needs to be clearly aware about the permissions granted to the web page using Web NFC.

8.4.4 Store site URL as record identifier when writing data

When pushing an NDEF message , the registrable domain , serialized , of the current settings object must be stored as the record identifier in each top-level NDEF Record .

8.4.5 Warn risk of physical location leak

When listening for and pushing NFC content , the UA may warn the user that the given origin may be able to infer physical location.

8.4.6 Restrict automatic handling

The payload data on NFC content is untrusted, and must not be used by the UA to do automatic handling such as opening a web page with a URL found in an NFC tag , unless the user approves that.

9. Data Representation

9.1 The NDEFMessage interface

The content of any NDEF message is exposed by the NDEFMessage interface:

[Exposed=Window]
interface NDEFMessage {
  constructor(NDEFMessageInit messageInit);
  readonly attribute FrozenArray<NDEFRecord> records;
};
dictionary NDEFMessageInit {
  required sequence<NDEFRecordInit> records;
};

The records property represents a list of NDEF record s defining the NDEF message .

The NDEFMessageInit dictionary is used to initialize a NDEF message .

9.2 The NDEFRecord interface

The content of any NDEF record is exposed by the NDEFRecord interface:

[Exposed=Window]
interface NDEFRecord {
  constructor(NDEFRecordInit recordInit);
  readonly attribute USVString recordType;
  readonly attribute USVString? mediaType;
  readonly attribute USVString id;
  readonly attribute DataView? data;
  readonly attribute USVString? encoding;
  readonly attribute USVString? lang;
  sequence<NDEFRecord> toRecords();
};
dictionary NDEFRecordInit {
  required USVString recordType;
  USVString mediaType;
  USVString id;
  USVString encoding;
  USVString lang;
  any data;
};

A NDEFRecord object has the following internal slots :

Internal slot Initial value Description ( non-normative )
[[PayloadData]] Empty byte sequence . A byte sequence representing the whole or a subset of the PAYLOAD field data.

The mediaType property represents the MIME type of the NDEF record payload.

The recordType property represents the NDEF record types.

The id property represents the record identifier , which is an absolute or relative URL. The required uniqueness of the identifier is guaranteed by the generator, as such only absolute URLs based on the origin of the browsing content can be written using this specification.

Note
The NFC NDEF specifications uses the terms "message identifier" and "payload identifier" instead of record identifier , but the identifier is tied to each record and not the message (collection of records), and it may be present when no payload is.

The encoding attribute represents the encoding name used for encoding the payload in the case it is textual data.

The lang attribute represents the language tag of the payload in the case that was encoded.

A language tag is a string that matches the production of a Language-Tag defined in the [ BCP47 ] specifications (see the IANA Language Subtag Registry for an authoritative list of possible values). That is, a language range is composed of one or more subtags that are delimited by a U+002D HYPHEN-MINUS ("-"). For example, the ' en-AU ' language range represents English as spoken in Australia, and ' fr-CA ' represents French as spoken in Canada. Language tags that meet the validity criteria of [ RFC5646 ] section 2.2.9 that can be verified without reference to the IANA Language Subtag Registry are considered structurally valid.

The data property represents the [[PayloadData]] bytes of the NDEF Record .

The toRecords() method, when invoked, MUST return the result of running convert NDEFRecord.[[PayloadData]] bytes with the NDEF Record .

The NDEFRecordInit dictionary is used to initialize an NDEF record with its record type recordType , and optional record identifier id and payload data data .

Additionally, there are additional optional fields that are only applicable for certain record types :

The mapping from data types of an NDEFRecordInit to NDEF record types is presented in the algorithmic steps which handle the data and described in the §  10.12 Parsing content and §  10.9 Writing or pushing content sections.

To convert NDEFRecord.[[PayloadData]] bytes given a record , run these steps:

  1. Let bytes be record . [[PayloadData]] .
  2. Let recordType be the value of record 's recordType attribute.
  3. If the recordType value is " smart-poster ", or an external type name , then return the result of running parse records from bytes on bytes . Re- throw any exceptions.
  4. Otherwise, throw a " NotSupportedError " DOMException and abort these steps.

9.3 The record type string

This string defines the allowed record types for a NDEFRecord . The §  9.4 Data mapping section describes how it is mapped to NDEF record types.

A set of known standardized values exists, but it is also possible for organizations to create their own custom external type names .

The " empty " string
The value representing empty NDEFRecord .
The " text " string
The value representing a Text record .
The " url " string
The value representing a URI record .
The " smart-poster " string
The value representing a Smart poster record.
The " absolute-url " string
The value representing a absolute-URL record .
The " mime " string
The value representing a MIME type record .
The " unknown " string
The value representing an unknown record .
An external type name
A DOMString representing a custom type for the external type record . The type must follow the external type name ABNF.
ext-type             = reg-name ":" custom-type
custom-type          = 1*(ALPHA / DIGIT / other)
DIGIT                = %x30-39
ALPHA                = %x41-5A / %x61-7A   ; A-Z / a-z
other                = "(" / ")" / "+" / "," / "-" / ":" / "=" /
"@"
/
";"
/
"$"
/
"_"
/
"!"
/
"*"
/
"'"
/
"."

The reg-name value is a registrable domain owned by the issuing organization, a " : " and a type, e.g. " w3.org:member ". And additional ABNF exists for well-known type records :

wkt-type
=
(ALPHA
/
DIGIT)
*(ALPHA
/
DIGIT
/
other)

Note

The NFC Record Type Definition (RTD) Technical Specification defines every type in the well-known type records and external type records in terms of URNs, but only a subset of the URN is actually stored in the NDEF record 's TYPE field , which corresponds to the above two ABNFs.

A local type name
A DOMString that MUST start with lowercase letter or a number, representing a type for a NFC Forum local type , typically used in a record of an NDEFMessage that is the payload of a parent NDEFRecord , for instance in a smart poster . The context of the local type is the parent record whose payload is the NDEFMessage to which this record belongs. The value MUST NOT be equal to any other record type s defined in this API.

Any implementation of Web NFC MUST transparently expose chunked records as single logical records, therefore unchanged record s are not explicitly represented.

Two well-known type s (including any NFC Forum local type and any NFC Forum global type ) MUST be compared character by character in case-sensitive manner.

Two external types MUST be compared character by character, in case-insensitive manner.

The binary representation of any well-known type and external type MUST be written as a relative URI (RFC 3986), omitting the namespace identifier (NID) " nfc " and namespace specific string (NSS) " wkt " and " ext ", respectively, i.e. omitting the " urn:nfc:wkt: " and " urn:nfc:ext: " prefixes. For instance, " urn:nfc:ext:company.com:a" is stored as " company.com:a`" and the well-known type of a Text record is " urn:nfc:wkt:T ", but it is stored as " T ".

9.4 Data mapping

The mapping from data types of an NDEFRecordInit to NDEF record types, as used in the §  10.9 Writing or pushing content section is as follows:

recordType mediaType data record type TNF field TYPE field
" empty " unused unused Empty record 0 unused
" text " unused BufferSource or
DOMString
Well-known type record 1 " T "
" url " unused DOMString Well-known type record 1 " U "
" smart-poster " unused NDEFMessage Well-known type record 1 " Sp "
local type name unused BufferSource Local type record* 1 local type name
" mime " MIME type BufferSource MIME type record 2 MIME type
" absolute-url " unused DOMString url Absolute-URL record 3 Absolute-URL
external type name unused BufferSource or
NDEFMessage
External type record 4 external type name
" unknown " unused BufferSource Unknown record 5 unused

* A local type record has to be embedded with the NDEFMessage payload of another record.

The mapping from NDEF record types to NDEFRecord , as used for incoming NDEF message s described in the §  10.12 Parsing content section, is as follows.

record type TNF field
TYPE field recordType mediaType
Empty record 0 unused " empty " undefined
Well-known type record 1 " T " " text " undefined
Well-known type record 1 " U " " url " undefined
Well-known type record 1 " Sp " " smart-poster " undefined
Local type record* 1 local type name local type name undefined
MIME type record 2 MIME type " mime " The MIME type used in the NDEF record
Absolute-URL record 3 URL " absolute-url " undefined
External type record 4 external type name external type name undefined
Unknown record 5 unused " unknown " undefined

10. The NDEFReader and NDEFWriter objects

The objects provide a way for the browsing context to use NFC functionality. They allow for pushing NDEF message s to NFC tag s or NFC peer s within range, and to act on incoming NDEF message s either from an NFC tag or an NFC peer .
typedef (DOMString or BufferSource or NDEFMessageInit) NDEFMessageSource;
[SecureContext, Exposed=Window]
interface NDEFWriter {
  constructor();
  Promise<void> push(NDEFMessageSource message, optional NDEFPushOptions options={});
};
[SecureContext, Exposed=Window]
interface NDEFReader : EventTarget {
  

  constructor();
  attribute EventHandler onerror;

  attribute EventHandler onreading;
  Promise<void> scan(optional NDEFScanOptions options={});
};
[SecureContext, Exposed=Window]
interface NDEFReadingEvent : Event {
  constructor(DOMString type, NDEFReadingEventInit readingEventInitDict);
  readonly attribute DOMString serialNumber;
  [SameObject] readonly attribute NDEFMessage message;
};
dictionary NDEFReadingEventInit : EventInit {
  DOMString? serialNumber = "";
  required NDEFMessageInit message;
};

The NDEFMessageSource is a union type representing argument types accepted by the push() method.

The NDEFReadingEvent is the event being dispatched on new NFC readings. The serialNumber property represents the serial number of the device used for anti-collision and identification, or empty string in case none is available. The message is an NDEFMessage object.

NDEFReadingEventInit is used to initialize a new event with a serial number and the NDEFMessageInit data via the message member. If serialNumber is not present or is null , empty string will be used to init the event.

Note

Though most tags will have a stable unique identifier (UID), not all have one and some tags even create a random number on each read. The serial number usually consists of 4 or 7 numbers, separated by : .

The NDEFWriter is an object used for writing data to NFC devices such as tags.

An NDEFWriter object has the following internal slots :

Internal Slot Initial value Description ( non-normative )
[[PushOptions]] null The NDEFPushOptions value for writer.
[[PushMessage]] null The NDEFMessage to be written. It is initially unset.

The NDEFReader is an object used for reading data when a device, such as a tag, is within the magnetic induction field.

An NDEFReader object has the following internal slots :

Internal Slot Initial value Description ( non-normative )
[[Id]] An empty string . The NDEFScanOptions . id value.
[[RecordType]] undefined The NDEFScanOptions . recordType value.
[[MediaType]] An empty string . The NDEFScanOptions . mediaType value.
[[Signal]] undefined The NDEFScanOptions . signal to abort the operation.
Note

Note that the internal slots of NDEFReader come from the options passed to NDEFReader.scan() . Therefore there is maximum one filter associated with any given NDEFReader object and successive invocations of NDEFReader.scan() with new options will replace existing filters.

The onreading is an EventHandler which is called to notify that new reading is available.

The onerror is an EventHandler which is called to notify that an error happened during reading.

10.1 NFC state associated with the settings object

The relevant settings object of the active document of a browsing context which supports NFC has an associated NFC state record with the following internal slots :

Internal Slot Initial value Description ( non-normative )
[[Suspended]] false A boolean flag indicating whether NFC functionality is suspended or not, initially false .
[[ActivatedReaderList]] empty set A set of NDEFReader instances.
[[PendingPush]] empty A < promise , writer > tuple where promise holds a pending Promise and writer holds an NDEFWriter .

The activated reader objects is the value of the [[ActivatedReaderList]] internal slot.

The pending push tuple is the value of the [[PendingPush]] internal slot.

NFC is suspended if the [[Suspended]] internal slot is true .

To suspend NFC , set the [[Suspended]] internal slot to true .

To resume NFC , set the [[Suspended]] internal slot to false .

Note

Internal slots are used only as a notation in this specification, and implementations do not necessarily have to map them to explicit internal properties.

10.2 Handling NFC adapters

Implementations MAY use multiple NFC adapter s according to the algorithmic steps described in this specification.

10.3 Handling visibility change

When the user agent determines that the visibility state of the responsible document of the current settings object changes, it must run these steps:

  1. Let document be the responsible document of the current settings object .
  2. If document 's visibility state is "visible" , resume NFC and abort these steps.
  3. Otherwise, suspend NFC and attempt to abort a pending push operation .

The term suspended refers to NFC operations being suspended, which means that no NFC content is pushed by NDEFWriter s, and no received NFC content is presented to any NDEFReader while being suspended.

10.4 Aborting pending push operation

To attempt to abort a pending push operation on an environment settings object , perform the following steps:

  1. If there is no pending push tuple tuple , abort these steps.
  2. If tuple 's writer has already initiated an ongoing NFC data transfer, abort these steps.
  3. Reject tuple 's promise with an " AbortError " DOMException and abort these steps.
    Note

    Rejecting the promise will clear the pending push tuple .

10.5 Releasing NFC

To release NFC on an environment settings object , perform the following steps:

  1. Suspend NFC .
  2. Attempt to abort a pending push operation .
  3. Stop the dispatch NFC content steps.
  4. Clear the activated reader objects .
  5. Release the NFC resources associated with nfc on the underlying platform.

The UA must release NFC given the document's relevant settings object as additional unloading document cleanup steps .

10.6 The NDEFPushOptions dictionary

dictionary NDEFPushOptions {
  NDEFPushTarget target = "any";
  boolean ignoreRead = true;
  boolean overwrite = true;
  AbortSignal? signal;
};

The target property denotes the intended target for the pending push() operation.

When the value of the ignoreRead property is true , the push algorithm will skip invoking the NFC reading algorithm for an NFC tag .

When the value of the overwrite property is false , the push algorithm will read the NFC tag regardless of the ignoreRead value to determine if it has NDEF records on it, and if yes, it will not execute any pending push.

The signal property allows to abort the push() operation.

10.7 The NDEFPushTarget enum

This enum defines the set of intended target values for the push() operation.

enum NDEFPushTarget {
  "tag",
  "peer",
  "any"
};

tag
The enum value representing the intended target for the push() operation to be a NFC tag .
peer
The enum value representing the intended target for the push() operation to be a NFC peer .
any
The enum value representing the intended target for the push() operation to be a NFC tag or a NFC peer .

10.8 The NDEFScanOptions dictionary

To describe which messages an application is interested in, the NDEFScanOptions dictionary is used:

dictionary NDEFScanOptions {
  USVString id = "";
  USVString recordType;
  USVString mediaType = "";
  AbortSignal? signal;
};

The signal property allows to abort the scan() operation.

The id property denotes the URL pattern which is used for matching the record identifier of individual NDEF Record s which are being read. The default value "" means that no matching is performed.

The recordType property denotes the string value which is used for matching the record type of each NDEFRecord object in an NDEF message . If the dictionary member is not present , then it will be ignored by the NFC listen algorithm .

The mediaType property denotes the match pattern which is used for matching the mediaType property of each NDEFRecord object in an NDEF message . The default value "" means that no matching is performed.

Example 14 : Filter accepting only JSON content from https://www.w3.org
const options = {
  id: "https://www.w3.org/*",  // any path from the domain is accepted
  mediaType: "application/*json"  // any JSON-based MIME type
}

Example 15 : Filter which only accepts binary content from a given path for w3 domain and its subdomains
const options = {
  id: "https://w3.org/info/restaurant/daily-menu/",
  mediaType: "application/octet-stream"
}

10.9 Writing or pushing content

This section describes how to write an NDEF message to an NFC tag or how to push it to an NFC peer device when it is next time in proximity range before a timer expires. At any time there is a maximum of two NDEF message s that can be set for pushing for an origin : one targeted to NFC tag s and one to NFC peer s, until the current message is sent or the push is aborted.

10.9.1 The push() method

The NDEFWriter.push method, when invoked, MUST run the push a message algorithm:
  1. Let p be a new Promise object.
  2. Let message be the first argument.
  3. Let options be the second argument.
  4. If there is no underlying NFC Adapter , or if a connection cannot be established, then reject p with a " NotSupportedError " DOMException and return p .
  5. If the UA is not allowed to access the underlying NFC Adapter (e.g. a user preference), then reject p with a " NotReadableError " DOMException and return p .
  6. If pushing data is not supported by the underlying NFC Adapter , then reject p with a " NotSupportedError " DOMException and return p .
  7. If the algorithm is not triggered by user activation , then reject p with a " NotAllowedError " DOMException and return p .
  8. Let signal be the options ’ dictionary member of the same name if present, or null otherwise.
  9. If signal ’s aborted flag is set, then reject p with an " AbortError " DOMException and return p .
  10. If signal is not null , then add the following abort steps to signal :
    1. Run the abort a pending push operation on the environment settings object .
  11. React to p :
    1. If p was settled (fulfilled or rejected), then clear the pending push tuple if it exists.
  12. Return p and run the following steps in parallel :
    1. An implementation MAY reject p with a " NotSupportedError " DOMException and abort these steps.
      Note

      The UA might abort message push at this point. The reasons for termination are implementation details. For example, the user could have has set a preference to allow a given origin only to read, write, or push data to peers. Also, the implementation might be unable to support the requested operation.

    2. Let output be the notation for the NDEF message to be created by UA, as the result of passing message to create NDEF message . If this throws an exception, reject p with that exception and abort these steps.
    3. Attempt to abort a pending push operation .
      Note

      A push replaces all previously configured push operations.

    4. Set this .[[PushOptions]] to options .
    5. Set this .[[PushMessage]] to output .
    6. Set pending push tuple to ( this , p ).
    7. Run the start the NFC push steps whenever an NFC device device comes within communication range.
    8. Note

      If NFC is suspended , continue waiting until promise is aborted by the user or an NFC device comes within communication range.

To start the NFC push , run these steps:
  1. Let p be the pending push tuple 's promise.
  2. Let writer be the pending push tuple 's writer.
  3. Let options be writer .[[PushOptions]].
  4. Let target be options ' target.
  5. If the NFC device in proximity range does not expose NDEF technology for formatting or writing, then reject p with a " NotSupportedError " DOMException and return p .
  6. Verify the following conditions:
  7. In case of success, run the following steps:
    1. If device is an NFC tag ,
    2. Let output be writer .[[PushMessage]].
    3. Initiate data transfer to device using output as buffer, using the NFC adapter in communication range with device .
      Note

      If the NFC device in proximity range is an unformatted NFC tag that is NDEF -formatable, format it and write output as buffer.

      Note

      Multiple adapters should be used sequentially by users. There is very little likelihood that a simultaneous tap will happen on two or multiple different and connected NFC adapter s. If it happens, the user will likely need to repeat the taps until success, preferably one device at a time. The error here gives an indication that the operation needs to be repeated. Otherwise the user may think the operation succeeded on all connected NFC adapter s.

    4. If the transfer fails, reject p with " NetworkError " DOMException and abort these steps.
    5. When the transfer has completed, resolve p .

10.9.2 Obtaining push permission

To obtain push permission , run these steps:

  1. If there is a prearranged trust relationship , return true .
  2. Run the query a permission steps for the Web NFC permission name until completion.
    1. If it resolved with " granted " (i.e. an expressed permission has been granted to the origin and global object using the Permissions API), return true .
    2. Otherwise, if it resolved with " prompt " , then optionally request permission from the user for the Web NFC permission name . If that is granted, return true .
      Issue 1

      The request permission steps are not yet clearly defined. At this point the UA asks the user about the policy to be used with the Web NFC permission name for the given origin and global object , if the user grants permission, return true .

  3. Return false .

10.10 Creating content

10.10.1 Creating NDEF message

To create NDEF message given a message run these steps:

  1. If the message parameter is not of type defined by the NDEFMessageSource union, throw a TypeError and abort these steps.
  2. If the message parameter is of NDEFMessageInit type, and message 's records is empty , throw a TypeError and abort these steps.
  3. Let output be the notation for the NDEF message to be created by the UA as a result of these steps.
  4. For each record in the list message 's records, run the following steps, or make sure that the underlying platform provides equivalent values to ndef :
    1. If record 's recordType is undefined :
      1. If record 's data is undefined , reject promise a TypeError and abort these steps.
      2. Otherwise, if the type of record 's data is DOMString , then set record 's recordType to " text ".
      3. Otherwise, set record 's recordType to " mime ".
    2. Let ndef be the result of passing record to the algorithm below switching on record 's recordType. If the algorithm throws an exception e , reject promise with e and abort these steps.
      " empty "
      " text "
      " url "
      " mime "
      external type name
      local type name
      unmatched type
    3. If message is of type NDEFMessageInit and its id is not null :
    4. Add ndef to output .

10.10.2 Mapping empty record to NDEF

To map empty record to NDEF given a record , run these steps:

  1. If record 's mediaType is not undefined , throw a TypeError and abort these steps.
  2. Let ndef be the notation for the NDEF record to be created by the UA.
  3. Set the ndef 's TNF field to 0 ( empty record ).
  4. Set the ndef 's IL field to 0 .
  5. Set ndef 's TYPE LENGTH field , and PAYLOAD LENGTH field to 0 , and omit TYPE field and PAYLOAD field .
  6. Return ndef .

10.10.3 Mapping string to NDEF

To map text to NDEF given a record , run these steps:

Note

This is useful when clients specifically want to write text in a well-known type record . Other options would be to use the value " mime " with an explicit MIME type text type, which allows for better differentiation, e.g. when using " text/xml ", or " text/vcard ".

  1. If record 's mediaType is not undefined , throw a TypeError and abort these steps.
  2. If the type of record 's data is not a DOMString or a BufferSource , throw a TypeError and abort these steps.
  3. Let documentLanguage be the document element 's lang attribute.
  4. If documentLanguage is the empty string, set it to " en ".
  5. Let language be record 's lang if it exists , or else to documentLanguage .
  6. Let encoding label be record 's encoding if it exists , or " utf-8 ".
  7. If encoding label is not equal to " utf-8 ", " utf-16 ", " utf-16le " or " utf-16be " throw a TypeError .
  8. Let encoding name be the name obtained from encoding label .
  9. Let header be a byte constructed the following way:
    1. If encoding name is equal to UTF-8, set bit 7 to the value 0 , or else set the value to 1 .
    2. Set bit 6 to the value 0 (reserved).
    3. Let languageLength be the length of the language string .
    4. If languageLength cannot be stored in 6 bit ( languageLength > 63), throw a SyntaxError .
    5. Set bit 5 to bit 0 to languageLength .
  10. Let data be an empty byte sequence .
    1. Set the first byte (position 0) of data to header .
    2. Set position 1 (second byte ) to position languageLength of data to language .
    3. Switch on the type of record 's data:
      DOMString
      1. Let stream be the resulting byte stream of running UTF-8 encode on record 's data.
      2. Read bytes from stream into data (from position languageLength + 1) until read returns end-of-stream .
      BufferSource
      1. Set bytes from record 's data into data (from position languageLength + 1) .
  11. Set length to the length of data .
  12. Let ndefRecord be the notation for the NDEF record to be created by the UA.
    1. Set the ndefRecord 's TNF field to 1 ( well-known type record ).
    2. Set the ndefRecord 's TYPE field to " T " ( 0x54 ).
    3. Set the ndefRecord 's PAYLOAD LENGTH field to length .
    4. If length > 0 , set the ndefRecord 's PAYLOAD field to data .
  13. Return ndefRecord .

10.10.4 Mapping URL to NDEF

To map a URL to NDEF given a record , run these steps:

  1. If record 's mediaType is not undefined , throw a TypeError and abort these steps.
  2. If record 's data is not a DOMString , throw a TypeError and abort these steps.
  3. Let url be the result of parsing record 's data.
  4. If url is failure, throw a TypeError and abort these steps.
  5. Let serializedURL be serialization of url .
  6. Match the URI prefixes as defined in NFC Forum Technical Specifications , URI Record Type Definition specification, Section 3.2.2, against the serializedURL .
  7. Let prefixString be the matched prefix or else the empty string .
  8. Let prefixByte be the corresponding prefix number, or else 0 .
  9. Let shortenedURL be serializedURL with prefixString removed from the start of the string .
  10. Let data be an empty byte sequence .
    1. Set the first byte of data to prefixByte .
    2. Let stream be the resulting byte stream of running UTF-8 encode on shortenedURL .
    3. Read bytes from stream into data (from position 1) until read returns end-of-stream .
  11. Set length to the length of data .
  12. Let ndefRecord be the notation for the NDEF record to be created by the UA.
    1. Set the ndefRecord 's TNF field to 1 ( well-known type record ).
    2. Set the ndefRecord 's TYPE field to " U " ( 0x55 ).
    3. Set the ndefRecord 's PAYLOAD LENGTH field to length .
    4. If length > 0 , set the ndefRecord 's PAYLOAD field to data .
  13. Return ndefRecord .

10.10.5 Mapping binary data to NDEF

To map binary data to NDEF given a record , run these steps:

  1. If the type of a record 's data is not a BufferSource , throw a TypeError and abort these steps.
  2. Let mimeTypeRecord be the MIME type returned by running parse a MIME type on record 's mediaType.
    1. If mimeTypeRecord is failure, let mimeTypeRecord be a new MIME type record whose type is " application ", and subtype is " octet-stream ".
  3. Set arrayBuffer to record 's data.
  4. Set length to arrayBuffer .[[ArrayBufferByteLength]].
  5. Set data to arrayBuffer .[[ArrayBufferData]].
  6. Let ndefRecord be the notation for the NDEF record to be created by the UA.
    1. Set the ndefRecord 's TNF field to 2 ( MIME type ).
    2. Set the ndefRecord 's TYPE field to the result of serialize a MIME type with mimeTypeRecord as the input.
    3. Set the ndefRecord 's PAYLOAD LENGTH field to length .
    4. If length > 0 , set the ndefRecord 's PAYLOAD field to data .
  7. Return ndefRecord .

10.10.6 Mapping external data to NDEF

To map external data to NDEF given a record , run these steps:

  1. If record 's mediaType is not undefined , throw a TypeError and abort these steps.
  2. If the type of a record 's data is not a BufferSource , throw a TypeError and abort these steps.
  3. Set arrayBuffer to record 's data.
  4. Set length to arrayBuffer .[[ArrayBufferByteLength]].
  5. Set data to arrayBuffer .[[ArrayBufferData]].
  6. Let ndefRecord be the notation for the NDEF record to be created by the UA.
    1. Set ndefRecord 's TNF field to 4 ( external type record ).
    2. Set the ndefRecord 's TYPE field to record 's recordType.
    3. Set the ndefRecord 's PAYLOAD LENGTH field to length .
    4. If length > 0 , set the ndefRecord 's PAYLOAD field to data .
  7. Return ndefRecord .

10.10.7 Mapping local type to NDEF

To map local type to NDEF given a record , run these steps:

  1. If record 's mediaType is not undefined , throw a TypeError and abort these steps.
  2. If the type of a record 's data is not a BufferSource , throw a TypeError and abort these steps.
  3. Set arrayBuffer to record 's data.
  4. Set length to arrayBuffer .[[ArrayBufferByteLength]].
  5. Set data to arrayBuffer .[[ArrayBufferData]].
  6. Let ndefRecord be the notation for the NDEF record to be created by the UA.
    1. Set the ndefRecord 's TYPE field to record 's recordType.
    2. If record 's recordType is a standard local type to smart poster or a handover record, then set ndefRecord 's TNF field to 1 ( well-known type record ), otherwise set ndefRecord 's TNF field to 4 ( external type record ).
    3. Set the ndefRecord 's PAYLOAD LENGTH field to length .
    4. If length > 0 , set the ndefRecord 's PAYLOAD field to data .
  7. Return ndefRecord .

10.10.8 Creating a record identifier

To create a record identifier given URL string id , run these steps:

  1. Let origin be the current settings object 's origin.
  2. Let host be origin 's host, serialized .
  3. Let urlRecord be the result of parsing id with " https:// " + host as the base URL.
  4. If any of the following cases matches, throw a TypeError and abort these steps:
    • If urlRecord is failure.
    • If urlRecord 's protocol is not equal to "https: ".
    • If urlRecord 's host doesn't end with host 's registrable domain .
  5. Let identifier be urlRecord , serialized .
  6. Return identifier .

10.11 Listening for content

If there are any NDEFReader instances in activated reader objects then the UA MUST listen to NDEF message s.

To listen for NFC content , the client MUST activate an NDEFReader instance by calling NDEFReader.scan() . When attaching an event listener for the " reading " event on it, NFC content is accessible to the client.

Each NDEFReader can accept NDEF message s based on data type, and record identifier (URL) filters.

Filtering by a record identifier URL pattern, means that it will be matched against the URLs found in the NDEF record s' ID field , thus the presence of such is required.

10.11.1 Match patterns

A match pattern is defined by the following ABNF:

match-pattern  = top-level-type "/" [ tree "." ] subtype [ "+" suffix ] [ ";" parameters ]
top-level-type = "*" / < VCHAR except "/" and "*" >
subtype
=
"*"
/
<
VCHAR
except
"+"
>

A match pattern is a glob used for matching MIME type s, for instance the pattern " application/*+json " matches " application/calendar+json ", but does not match " application/json ". The pattern " */*json ", on the other hand, matches both.

10.11.2 URL patterns

A URL pattern is a URL record that can be used to match the optional record identifier of every NDEF record ID field . A valid URL pattern is a valid URL record whose scheme component is equal to " https ".

A URL pattern 's scheme , host and path components that are used by the URL pattern match algorithm have the following matching rules:
URL pattern component Matching rule for record identifier
host exact match or ends with ( URL pattern 's host prepended with " . ").
path If URL pattern 's path is " /* ", match any record identifier path. Otherwise, begins with URL pattern 's path .

Note

For example, ' https://mydomain.com/* ' will match ' https://service.mydomain.com/myapp/ ' and ' https://info.mydomain.com/general/ ', while ' https://app.mydomain.com/contacts ' will match ' https://app.mydomain.com/contacts ' and ' https://app.mydomain.com/contacts/all ' The ' * ' is a valid character for the URL path component, therefore, ' https://www.mydomain.com/* ' pattern will match both ' https://www.mydomain.com/* ' and ' https://www.mydomain.com/service ' URLs.

10.11.3 URL pattern match algorithm

To match record identifier with URL pattern for a given record identifier and URL pattern , run these steps:
  1. Let raw id be a record identifier passed to this algorithm.
  2. Let raw pattern be a URL pattern passed to this algorithm.
  3. If raw id and raw pattern are empty string s, return true .
  4. Let id be the result of running the basic URL parser on raw id .
  5. If id is failure, return false .
  6. Let pattern be the result of running the basic URL parser on raw pattern .
  7. If pattern is failure, return false .
  8. Let subdomain pattern be the result of prepending " . " to pattern 's host .
  9. If id 's host does not end with subdomain pattern and id 's host is not equal to pattern 's host , return false .
  10. If pattern 's path is equal to " /* ", return true .
  11. If id 's path begins with pattern 's path , return true .
  12. Otherwise, return false .

10.11.4 The scan() method

Incoming NFC content is matched using NDEFReader instances.

When the NDEFReader.scan method is invoked, the UA MUST run the following NFC listen algorithm :

  1. Let p be a new Promise object.
  2. Let reader be the NDEFReader instance.
  3. Let options be first argument.
  4. For each key value of options :
    1. If key equals " signal " and value is not undefined , set reader . [[Signal]] to value .
    2. Otherwise, if key equals " id ", set reader . [[Id]] to value , prepended with " https:// ".
    3. Otherwise, if key equals " recordType ", set reader . [[RecordType]] to value .
    4. Otherwise, if key equals " mediaType ", set reader . [[MediaType]] to value .
  5. If there is no underlying NFC Adapter , or if a connection cannot be established, then reject p with a " NotSupportedError " DOMException and return p .
  6. If the UA is not allowed to access the underlying NFC Adapter (e.g. a user preference), then reject p with a " NotReadableError " DOMException and return p .
  7. If the algorithm is not triggered by user activation , then reject p with a " NotAllowedError " DOMException and return p .
  8. If reader . [[Signal]] 's aborted flag is set, then reject p with a " AbortError " DOMException and return p .
  9. If reader . [[Signal]] is not null , then add the following abort steps to reader . [[Signal]] :
    1. Remove the NDEFReader instance from the activated reader objects .
    2. If the activated reader objects is empty , then make a request to stop listening to NDEF message s on all NFC adapter s.
  10. Run the following steps in parallel :
    1. If the obtain reading permission steps return false , then reject p with a " NotAllowedError " DOMException and return p .
    2. If this is the first listener being set up, then make a request to all NFC adapter s to listen to NDEF message s.
    3. If the request fails, then the UA MAY reject p with a " NotSupportedError " DOMException and return p .
    4. If the reader . [[Id]] is not an empty string and it is not a valid URL pattern , then reject p with a " SyntaxError " DOMException and return p .
    5. Add reader to the activated reader objects .
    6. If the Document of the top-level browsing context is not visible (e.g. the user navigated to another page), then the registered activated reader objects still SHOULD continue to exist, but SHOULD become paused, i.e. the UA SHOULD NOT check and use them until the Document is visible again.
    7. Whenever the UA detects NFC technology, run the NFC reading algorithm .

To obtain reading permission , run these steps:

  1. If there is a prearranged trust relationship , return true .
  2. Otherwise, if the user has earlier denied permission for the calling origin for all future calls of scan() as well, then return false .
  3. Otherwise, UAs SHOULD ask for forgiveness with relevant information displayed to the user.
    Note

    The ask for forgiveness interaction might show choices like "block now" or "block forever", etc. If the user has chosen to "block forever" the given origin , it is the responsibility of the UA to remember these user choices for each origin , regardless of which NFC adapter is used, and consult them on later invocations.

    Note

    In this step UAs are advised to notify users about that reading NFC content may indirectly reveal the physical location of the user.

  4. Return true .

10.11.5 The NFC reading algorithm

To receive NDEF content, run the NFC reading algorithm :
  1. If NFC is suspended , abort these steps.
  2. If the NFC device in proximity range does not expose NDEF technology for reading or formatting, abort these steps. run the following sub-steps:
    1. For each Note NDEFReader This means there is no reading event generated when non- NDEF NFC technology comes in proximity range. This may change instance reader in future version of the specification. activated reader objects , run the following sub-steps:
      1. Fire an event named " error " at reader .
    2. Abort these steps.
  3. Let serialNumber be the device identifier as a series of numbers, or null if unavailable.
  4. If serialNumber is not null , set it to the string of U+003A ( : ) concatenating each number represented as ASCII hex digit , in the same order.
  5. Let message be a new NDEFMessage object, with message 's records set to the empty list .
  6. If the NFC device in proximity range is an unformatted NFC tag that is NDEF-formattable, let input be null . Otherwise, let input be the notation for the NDEF message which has been received.
    Note

    The UA SHOULD represent an unformatted NFC tag as an NDEF message containing no NDEF record s, i.e. an empty array for its records property.

  7. For each NDEF record which is part of input , run the following sub-steps:
    1. Let ndef be the notation for the current NDEF record with typeNameField corresponding to the TNF field and payload corresponding to the PAYLOAD field data.
    2. Let record be the result of parse an NDEF record on ndef .
    3. If record is not null , append record to message 's records.
  8. If NFC is not suspended , run the dispatch NFC content steps with given serialNumber and message .

10.11.6 Dispatching NFC content

To dispatch NFC content given a serialNumber of type serialNumber , message of type NDEFMessage , run these steps:

  1. For each NDEFReader instance reader in the activated reader objects , run the following sub-steps:
    1. If reader . [[Id]] is present and doesn't match any record 's id where record is an element of message , continue .
    2. If reader . [[RecordType]] is present and it is not equal to any record 's recordType where record is an element of message , continue .
    3. If reader . [[MediaType]] is not "" and it is not equal to any record 's mediaType where record is an element of message , continue .
    4. Fire an event named " reading " at reader using NDEFReadingEvent with its serialNumber attribute initialized to serialNumber and message attribute initialized to message .

10.12 Parsing content

10.12.1 Parsing records from bytes

To parse records from bytes given bytes , run these steps:
  1. Let records be the empty list.
  2. As long as there are unread bytes of bytes , run the following sub-steps:
    1. If the remaining length of bytes is less than 3 , abort these sub-steps.
    2. If any of the following steps requires reading bytes beyond the remaining length of bytes , return records .
    3. Let ndef be the notation for the current NDEF record
    4. Let header be the next byte of bytes .
      1. Let messageBegin ( MB field ) be the left most bit (bit 7) of header .
      2. If this is the first iteration of these sub-steps and messageBegin is false , return records .
      3. Let messageEnd ( ME field ) be bit 6 of header .
      4. Note
        As chunked records are not allowed as sub records, ignore bit 5 ( CF field ) is ignored.
      5. Let shortRecord ( SR field ) be bit 4 of header .
      6. Let hasIdLength ( IL field ) be bit 3 of header .
      7. Let ndef 's typeNameField ( TNF field ) be the integer value of bit 2-0 of header .
    5. Let typeLength be the integer value of next byte ( TYPE LENGTH field ) of bytes .
    6. If shortRecord is true , let payloadLength be the integer value of next byte ( PAYLOAD LENGTH field ) of bytes .
    7. Otherwise, let payloadLength be the integer value of the next 4 bytes of bytes .
    8. If hasIdLength is true , let idLength be the integer value of next byte ( ID LENGTH field ) of bytes , otherwise let it be 0 .
    9. If typeLength > 0, let ndef 's type be result of running UTF-8 decode on the next typeLength ( TYPE field ) bytes, orelse let type be the empty string.
    10. If idLength > 0, let ndef 's id be result of running UTF-8 decode on the next idLength ( ID field ) bytes, orelse let ndef 's id be the empty string.
    11. Let ndef 's payload be the byte sequence of the last payloadLength ( PAYLOAD field ) bytes, which may be 0 bytes.
    12. Let record be the result of parse an NDEF record on ndef .
    13. If record is not null , append record to records .
    14. If messageEnd is true , abort these sub-steps.
  3. Return records .

10.12.2 Parsing NDEF records

To parse an NDEF record given ndef into a record , run these steps:

  1. Set record 's id to ndef 's id .
  2. Set record 's lang to null .
  3. Set record 's encoding to null .
  4. If ndef 's typeNameField is 0 ( empty record ), then set record 's recordType to " empty ".
  5. If ndef 's typeNameField is 1 ( well-known type record ):
    1. Set record to the result of the algorithm below switching on ndef 's type :
      " T " ( 0x54 )
      " U " ( 0x55 )
      " Sp " ( 0x53 0x70 )
  6. If ndef 's typeNameField is 2 ( MIME type record ), then set record to the result of running parse an NDEF MIME type record on ndef , or make sure that the underlying platform provides equivalent values to the record object's properties.
  7. Otherwise, if ndef 's typeNameField is 3 ( absolute-URL record ), then set record to the result of running parse an NDEF absolute-URL record on ndef .
  8. Otherwise, if ndef 's typeNameField is 4 ( external type record ), then set record to the result of running parse an NDEF external type record on ndef , or make sure that the underlying platform provides equivalent values to the record object's properties.
  9. Otherwise, if ndef 's typeNameField is 5 ( unknown record ) then set record to the result of running parse an NDEF unknown record on ndef , or make sure that the underlying platform provides equivalent values to the record object's properties.

10.12.3 Parsing NDEF well-known T records

To parse an NDEF text record given a ndefRecord into a record , run these steps:

  1. Set record 's recordType to " text ".
  2. Let mimeType be a MIME type with type " text ", subtype " plain " and parameters equal to an empty ordered map.
  3. If ndefRecord 's PAYLOAD field is not present, set record . [[PayloadData]] to undefined and return record .
  4. Let header be the first byte of ndefRecord 's PAYLOAD field .
  5. Let languageLength be the value given by bit 5 to bit 0 of the header .
  6. Let language be the result of running ASCII decode on second byte to the languageLength + 1 byte, inclusive.
  7. Set record 's lang to language .
  8. Set record 's encoding be " utf-8 " if bit 7 ( MB field ) of header is equal to the value 0 , or else " utf-16be ".
  9. Let buffer be the byte sequence of ndefRecords 's PAYLOAD field .
  10. Set record . [[PayloadData]] to buffer .
  11. return record .

Note

10.12.4 Parsing NDEF well-known U records

To parse an NDEF URL record given a ndefRecord into a record , run these steps:

  1. Set record 's recordType to " url ".
  2. If ndefRecord 's PAYLOAD field is not present, set record . [[PayloadData]] to undefined and return record .
  3. Let buffer be the byte sequence of ndefRecords 's PAYLOAD field .
  4. Let prefixByte be the value of the first byte of buffer .
  5. If the value of prefixByte matches the URL expansion codes in the NFC Forum Technical Specifications URI Record Type Definition specification, Section 3.2.2, Table 3, then
    1. Let prefixString be the byte sequence value corresponding to the value of prefixByte .
    2. Set record . [[PayloadData]] to prefixString appended to buffer .
  6. Otherwise, if there is no match for prefixByte , set record . [[PayloadData]] to buffer .
  7. return record .

10.12.5 Parsing NDEF well-known Sp records

To parse an NDEF smart-poster record given a ndefRecord into a record , run these steps:

  1. Set record 's recordType to " smart-poster ".
  2. If ndefRecord 's PAYLOAD field is not present, set record . [[PayloadData]] to undefined and return record .
  3. Let buffer be the byte sequence of ndefRecords 's PAYLOAD field .
  4. Set record . [[PayloadData]] to buffer .
  5. return record .

10.12.6 Parsing NDEF MIME type records

To parse an NDEF MIME type record given a ndefRecord into a record , run these steps:

  1. Set record 's recordType to " mime ".
  2. Set record 's mediaType to the result of serialize a MIME type with mimeType as the input.
  3. Let buffer be the byte sequence of ndefRecords 's PAYLOAD field if that exists, or otherwise undefined .
  4. Set record . [[PayloadData]] to buffer .
  5. return record .

10.12.7 Parsing NDEF absolute-URL records

To parse an NDEF absolute-URL record given a ndefRecord into a record , run these steps:

  1. Set record 's recordType to " absolute-url ".
  2. Let buffer be the byte sequence of ndefRecords 's TYPE field .
  3. return record .

10.12.8 Parsing NDEF external type records

To parse an NDEF external type record given a ndefRecord into a record , run these steps:

  1. Set record 's recordType to the value of ndefRecord 's TYPE field .
  2. Let buffer be the byte sequence of ndefRecords 's PAYLOAD field if that exists, or otherwise undefined .
  3. Set record . [[PayloadData]] to buffer .
  4. return record .

10.12.9 Parsing NDEF unknown type records

To parse an NDEF unknown record given a ndefRecord into a record , run these steps:

  1. Set record 's recordType to " unknown ".
  2. Let buffer be the byte sequence of ndefRecords 's PAYLOAD field if that exists, or otherwise undefined .
  3. Set record . [[PayloadData]] to buffer .
  4. return record .

10.13 IDL Index

[Exposed=Window]
interface NDEFMessage {
  constructor(NDEFMessageInit messageInit);
  readonly attribute FrozenArray<NDEFRecord> records;
};
dictionary NDEFMessageInit {
  required sequence<NDEFRecordInit> records;
};
[Exposed=Window]
interface NDEFRecord {
  constructor(NDEFRecordInit recordInit);
  readonly attribute USVString recordType;
  readonly attribute USVString? mediaType;
  readonly attribute USVString id;
  readonly attribute DataView? data;
  readonly attribute USVString? encoding;
  readonly attribute USVString? lang;
  sequence<NDEFRecord> toRecords();
};
dictionary NDEFRecordInit {
  required USVString recordType;
  USVString mediaType;
  USVString id;
  USVString encoding;
  USVString lang;
  any data;
};
typedef (DOMString or BufferSource or NDEFMessageInit) NDEFMessageSource;
[SecureContext, Exposed=Window]
interface NDEFWriter {
  constructor();
  Promise<void> push(NDEFMessageSource message, optional NDEFPushOptions options={});
};
[SecureContext, Exposed=Window]
interface NDEFReader : EventTarget {
  

  constructor();
  attribute EventHandler onerror;

  attribute EventHandler onreading;
  Promise<void> scan(optional NDEFScanOptions options={});
};
[SecureContext, Exposed=Window]
interface NDEFReadingEvent : Event {
  constructor(DOMString type, NDEFReadingEventInit readingEventInitDict);
  readonly attribute DOMString serialNumber;
  [SameObject] readonly attribute NDEFMessage message;
};
dictionary NDEFReadingEventInit : EventInit {
  DOMString? serialNumber = "";
  required NDEFMessageInit message;
};
dictionary NDEFPushOptions {
  NDEFPushTarget target = "any";
  boolean ignoreRead = true;
  boolean overwrite = true;
  AbortSignal? signal;
};
enum NDEFPushTarget {
  "tag",
  "peer",
  "any"
};
dictionary NDEFScanOptions {
  USVString id = "";
  USVString recordType;
  USVString mediaType = "";
  AbortSignal? signal;
};

10.14 Acknowledgments

The editors would like to thank Jeffrey Yasskin, Anne van Kesteren, Anssi Kostiainen, Domenic Denicola, Daniel Ehrenberg, Jonas Sicking, Don Coleman, Salvatore Iovene, Rijubrata Bhaumik, and Wanming Lin for their contributions to this document.

Special thanks to Luc Yriarte and Samuel Ortiz for their initial work on exposing NFC to the web platform, and for their support for the current approach.

A. References

A.1 Normative references

[BCP47]
Tags for Identifying Languages . A. Phillips; M. Davis. IETF. September 2009. IETF Best Current Practice. URL: https://tools.ietf.org/html/bcp47
[dom]
DOM Standard . Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification . Ecma International. URL: https://tc39.es/ecma262/
[encoding]
Encoding Standard . Anne van Kesteren. WHATWG. Living Standard. URL: https://encoding.spec.whatwg.org/
[HTML]
HTML Standard . Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[infra]
Infra Standard . Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[mimesniff]
MIME Sniffing Standard . Gordon P. Hemsley. WHATWG. Living Standard. URL: https://mimesniff.spec.whatwg.org/
[NFC-NDEF]
NFC Data Exchange Format (NDEF) Technical Specification . NFC Forum. 24 July 2006. URL: http://members.nfc-forum.org/specs/spec_list/
[NFC-STANDARDS]
NFC Forum Technical Specifications . NFC Forum. 24 July 2006. URL: http://members.nfc-forum.org/specs/spec_list/
[PAGE-VISIBILITY]
Page Visibility (Second Edition) . Jatinder Mann; Arvind Jain. W3C. 29 October 2013. W3C Recommendation. URL: https://www.w3.org/TR/page-visibility/
[PERMISSIONS]
Permissions . Mounir Lamouri; Marcos Caceres; Jeffrey Yasskin. W3C. 25 September 2017. W3C Working Draft. URL: https://www.w3.org/TR/permissions/
[RFC2046]
Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types . N. Freed; N. Borenstein. IETF. November 1996. Draft Standard. URL: https://tools.ietf.org/html/rfc2046
[RFC2048]
Multipurpose Internet Mail Extensions (MIME) Part Four: Registration Procedures . N. Freed; J. Klensin; J. Postel. IETF. November 1996. Best Current Practice. URL: https://tools.ietf.org/html/rfc2048
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels . S. Bradner. IETF. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC5234]
Augmented BNF for Syntax Specifications: ABNF . D. Crocker, Ed.; P. Overell. IETF. January 2008. Internet Standard. URL: https://tools.ietf.org/html/rfc5234
[RFC5646]
Tags for Identifying Languages . A. Phillips, Ed.; M. Davis, Ed.. IETF. September 2009. Best Current Practice. URL: https://tools.ietf.org/html/rfc5646
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words . B. Leiba. IETF. May 2017. Best Current Practice. URL: https://tools.ietf.org/html/rfc8174
[url]
URL Standard . Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[WebIDL]
Web IDL . Boris Zbarsky. W3C. 15 December 2016. W3C Editor's Draft. URL: https://heycam.github.io/webidl/

A.2 Informative references

[NDEF-SIGNATURE]
NFC Forum Signature Record Type Definition . NFC Forum. 18 November 2010. URL: http://members.nfc-forum.org/specs/spec_list/
[NDEF-SMARTPOSTER]
NFC Forum Smart Poster Record Type Definition . NFC Forum. 24 July 2006. URL: http://members.nfc-forum.org/specs/spec_list/
[NDEF-TEXT]
NFC Forum Text Record Type Definition . NFC Forum. 14 August 2013. URL: http://members.nfc-forum.org/specs/spec_list/
[NDEF-URI]
NFC Forum URI Record Type Definition . NFC Forum. 24 July 2006. URL: http://members.nfc-forum.org/specs/spec_list/
[NFC-HANDOVER]
NFC Forum Connection Handover Technical Specification . NFC Forum. 16 January 2014. URL: http://members.nfc-forum.org/specs/spec_list/
[NFC-RTD]
NFC Record Type Definition (RTD) Technical Specification . NFC Forum. 24 July 2006. URL: http://members.nfc-forum.org/specs/spec_list/
[RFC3986]
Uniform Resource Identifier (URI): Generic Syntax . T. Berners-Lee; R. Fielding; L. Masinter. IETF. January 2005. Internet Standard. URL: https://tools.ietf.org/html/rfc3986
[RFC3987]
Internationalized Resource Identifiers (IRIs) . M. Duerst; M. Suignard. IETF. January 2005. Proposed Standard. URL: https://tools.ietf.org/html/rfc3987
[secure-contexts]
Secure Contexts . Mike West. W3C. 15 September 2016. W3C Candidate Recommendation. URL: https://www.w3.org/TR/secure-contexts/