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 (see https://www.nfc-forum.org/specs/spec_list/).

This document defines an API to enable selected use-cases based on NFC technology.

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.

Significant changes to this document since last publication are documented in the Changes section.

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

Implementations that use ECMAScript to implement the APIs defined in this document MUST implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL]], as this document uses that specification and terminology.

Terminology

The term browsing context refers to the environment in which Document objects are presented to the user. A given browsing context has a single origin and a single WindowProxy object, but it can have many Document objects, with their associated Window objects. The browsing context identifies the entity which invokes this API, which can be a web app, a web page, or an iframe.

The term incumbent settings object is defined in [[!HTML5]].

The term secure context is defined in [[!WEBAPPSEC]].

The term of executing algorithms in parallel is defined in [[!HTML5]].

URL is defined in [[!URL]].

The term document base URL is defined in [[!HTML5]].

The term URL path is defined in [[!URL]].

The term origin is defined in [[!HTML5]].

The term ASCII serialized origin is defined in [[!HTML5]].

The term URL pattern is defined in the URL patterns section.

The term match pattern is defined in the Match patterns section.

DOMString, ArrayBuffer, BufferSource and any are defined in [[!WEBIDL]].

DOMException, AbortError, SyntaxError, NotSupportedError, NotFoundError, NetworkError, SecurityError are defined in [[!DOM4]].

Promise, JSON and JSON.parse are defined in [[!ECMASCRIPT]].

The algorithms utf-8 encode, and utf-8 decode are defined in [[!ENCODING]].

IANA media types (formerly known as MIME types) are defined in RFC2046.

The term expressed permission refers to an act by the user, e.g. via user interface or setting or host device platform features, using which the user approves the permission of a browsing context to access the given functionality.

The term ask for forgiveness refers to some form of unobtrusive notification that informs the user of an operation while it is running. User agents SHOULD provide the user with means to ignore similar future operations from the same origin and advertise this to the user.

The term prearranged trust relationship means that the user agent has already established a trust relationship for a certain operation using a platform specific mechanism, so that an expressed permission from the user is not any more needed. See also this section in the Security and Privacy document.

The term obtain permission for a certain operation indicates that the user agent has either obtained expressed permission, or asks for forgiveness, or ensured a prearranged trust relationship exists.

NFC stands for Near Field Communications, 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 https://www.nfc-forum.org/specs/spec_list/ 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 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.

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.

An NDEF message encapsulates one or more application-defined NDEF records. NDEF is an abbreviation for NFC Forum Data Exchange Format, a lightweight binary message format. NDEF messages can be stored on an NFC tag or exchanged between NFC-enabled devices.

The term NFC content is a synonym for NDEF message, which can originate either from an NFC tag or an NFC peer.

An NDEF record is a part of an NDEF message that has a single associated type information to its payload. It is contains a Type Name Format (TNF) field, the payload size, the payload type, an optional identifier which is a URL, and a payload of maximum size of 2^32-1 bytes. The NFC Forum has standardized a small set of useful data types to be used in NDEF records, for instance text, URL, and binary data such as media. In addition, there are record types designed for more complex interactions, such as Smart Poster, and handover records.

The TNF (Type Name Format) field of the NDEF record can take binary values denoting the following NDEF record payload types:

TNF value NDEF record type
0 Empty
1 NFC Forum Well-Known Type
2 Media Type
3 Absolute URI
4 NFC Forum External Type
5 Unknown
6 Unchanged
7 Reserved

NFC Forum Well-Known Type includes record types text, URI, Smart Poster (containing a URI or other data and possible actions).

An NFC watch is a mechanism used for listening to and filtering Web NFC messages. It is defined in more detail in The watch() method section.

A Web NFC record is a special NDEF record of External Type specific to W3C Web NFC, which indicates that the containing NDEF message is targeted for browsing contexts using this API and contains information useful for handling the NDEF message with the algorithms defined in this API. The format of a Web NFC record is the following:

The Web NFC Id is a URL according to [[RFC3986]], with "https" scheme, and an ASCII serialized origin optionally followed by a URL path. It is used for matching Web NFC content with URL patterns specified by NFC watches.

A Web NFC message consists of a set of the NDEF records and a single Web NFC record.

The position of the Web NFC record within the Web NFC message is implementation specific, this specification only mandates its existence for a Web NFC message. It is not mandatory to a NDEF message.

The term Web NFC content denotes all Web NFC messages contained in an NDEF message, identified by their Web NFC Id within the NDEF message. This version of the specification supports one Web NFC message per NDEF message.

Part of the NDEF record is the NDEF Id field, which may or may not be present and it is meant for applications use. If it is present, according to the [[!NFC-STANDARDS]] it contains a maximum 256 octets long URL which is used for identifying the payload, in an application specific way. Although the NDEF Id could be used for containing e.g. an ASCII serialized origin associated with the NDEF record, it is not used in this version of the specification for record-level identification, since message-level identification is used by the means of the Web NFC Id. Also, the content of the NDEF Id is also contained in the Web NFC Id, and since NFC tags are rather small storages, this duplication is avoided in this version. When multiple Web NFC messages will be eventually supported within a single NDEF message, it would likely use the NDEF Id to store the same identifier for each NDEF record which is part of a given Web NFC message, which identifier will likely be an ASCII serialized origin associated with the Web NFC content.

The term trusted integrity NFC content refers to an NDEF message, or an NDEF record, which can be trusted for data integrity, i.e. the content is not changed by third party between writing and reading.

An NFC handover defines NFC Forum Well Known Types 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.

Introduction

In general, there are three groups of user scenarios for NFC:

NFC works using magnetic induction, meaning that the reader 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 RFIDs tags, but many of these are only supported by single vendors and not part of the NFC standards. Though certain devices support reading and writing to these, it is not a goal of this document to support proprietary tags or support interoperability with legacy systems.

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

  1. NFC Forum Type 1: This tag 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 96 bytes and 2 Kbytes. Communication speed is 106 kbit/sec.
  2. NFC Forum Type 2: This tag is also 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. In contrast to Type 1, Type 2 has anti-collision protection for dealing with multiple tags within the NFC field.
  3. NFC Forum Type 3: This tag is based on the Japanese Industrial Standard (JIS) X 6319-4, commonly known as FeliCa. The tags are preconfigured to be either rewritable or read-only. Memory availability is variable, theoretical memory limit is 1MByte per service. Communication speed is 106 kbit/sec. Like Type 2, it supports anti-collision protection.
  4. NFC Forum Type 4 (November 2010): This tag is based on the ISO/IEC 14443 like Type 1 and 2, but it support either NFC-A or NFC-B for communication. On top of that the tag may support the Data Exchange Protocol (aka ISO-DEP) defined in ISO/IEC 14443 (ISO/IEC 14443-4:2008 Part 4: Transmission protocol). Like Type 3, the tags are preconfigured to be either rewritable or read-only. Variable memory, up to 32 KB per service. Supports three different communication speeds 106 or 212 or 424 Kbits/s.

In addition to data types standardized for NDEF records by the NFC Forum, many commercial products, e.g. bus cards, door openers etc, use different card specific data and protocol extensions which require specific NFC chips (same vendor of card and reader) in order to work.

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

This document does not aim supporting all possible use cases of NFC technology, but only a few use cases which are considered relevant to be used by web pages in browsers, using the browser security model.

Examples

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

    var adapter = null;
    var id = null;
    navigator.nfc.requestAdapter().then((nfcAdapter) => {
      id = adapter.watch({}, onMessage);
    };

    function onMessage(message, url) {
      console.log("NDEF message received from URL " + url);
      if (message[0].kind == 'empty') {
        adapter.pushMessage([
         { kind: "text", type: "", data: “Initializing a passive tag”}]);
      }

      message.forEach((record) => {
        if (record.kind == "string") {
          console.log(“Data is string: “ + data);
        } else if (record.kind == "json") {
          processJSON(record.data);
        } else if (record.kind == "url") {
        console.log(“Data is URL: “ + record.data;
        } else if (record.kind == "opaque") {
        processBinary(data);
      });
    };

    function processBinary(data) {
      console.log("Binary data we know being a string: ");
      console.log(String.fromCharCode.apply(null, new Uint16Array(data)));
    };

    function processJSON(data) {
      var obj = JSON.parse(data);
      console.log("My data: " + obj.myProperty.toString());
    };
  
    navigator.nfc.requestAdapter().then((adapter) => {
        adapter.pushMessage([
          { kind: "text", type: "", data: “Data meant for peers”}])
        .then(() => { console.log("Message sent")})
        .catch(() => {console.log("Send failed, try again.")});
    };
  
    navigator.nfc.requestAdapter().then((adapter) => {
      console.log("Waiting for game state");
      adapter.watch({ url: "*://myserver/mygame/*"}, (message, url) => {
        console.log("Game state received from: " + url;
        console.log("Game state: " + message.data);
        // Now do some calculations and update the state.
        adapter.pushMessage([ data: { level: 3, points: 4500, lives: 3 } ])
          .then(() => { console.log("Send was successful")})
          .catch(() => { console.log("Send failed")});
      };
    });
  

Use Cases

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.

Reading NFC tags

  1. Reading NFC tags containing a Web NFC message, when a web page using the Web NFC API is open and in focus. For instance, a web page instructs the user to tap an NFC tag, and get information from the tag.
  2. Reading NFC tags containing other than Web NFC message, when a web page using the Web NFC API is open and in focus.
  3. Reading NFC tags when no web site using the Web NFC API is open or in focus. This use case is not supported in this version of the specification, and is has low priority for future versions as well.

Writing to NFC tags

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 NFC tags which already contains a Web NFC message with a different Web NFC Id (i.e. overwriting a web-specific tag).
  3. Writing to NFC tags which already contains a Web NFC message with the same Web NFC Id (i.e. updating own tag).
  4. Writing to other, writable NFC tags (i.e. overwriting a generic tag).

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

Sending data to NFC peer devices

In general, sending data to another Web 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 user agent will dispatch the content to an application registered and eligible to handle the content, and if that application is a browser which has a web page open and in focus that uses the Web NFC API and has set up a NFC watch to listen to Web NFC content, then the content is delivered to the web page through the parameters of an NFCMessageCallback.

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. This use case is not supported in this version of the specification.

Payment scenarios

The user buys goods in a store, and payments options include NFC. 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 the Web NFC API, 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. This use case is not supported in this version of the specification.

Features

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

  1. Support devices with single or multiple NFC adapters. If there are multiple adapters present when requesting an NFC adapter then the user agent MAY display a dialog for selecting one of them, or MAY otherwise choose a default adapter based on user settings or internal policy.
  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 Web NFC messages.
  4. Allow users to write a payload via NDEF records to compatible devices, such as writeable tags, when they come in range, as Web NFC messages.
  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.

NFC is usually deeply integrated into device platforms (e.g. Android, Windows, etc), because end-to-end user experience implications (e.g. users need to be presented platform specific dialogs for selecting applications and actions). Also, privacy and security related issues require platform specific solutions.

The various integrated technologies, wide variety of use cases, and platform integration issues make standardization of NFC for the web a challenge. Therefore this document makes a few simplifications in what use cases and data types are possible to handle by users of this API:

Security and Privacy

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

Chain of trust

Web pages using the NFC API 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 SHOULD make sure that when the user authorizes an NFC operation, 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 operations.

The content of Web NFC messages is not trusted, unless the user agent can safely assume that the content has not been change by third parties between writing and reading it, e.g. in the case of a prearranged trust relationship can be established.

Threats

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

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

Permissions and user prompts

User agents MUST NOT provide Web NFC API access to browsing contexts without complying with the security policies described in this document.

This specification attempts to help minimizing the user prompts needed to use the Web NFC API and tries to involve implicit policies which can 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.

The Permissions API SHOULD be supported by user agents for implementing NFC related [[permissions]]. The required permission name is "nfc". This allows saving user permissions for a given origin in a persistent database until revocation.

User agents MUST acquire user consent, i.e. expressed permission for for using the methods of this API, unless a prearranged trust relationship applies, or unless an implicit policy specified in this document allows it, eventually with an ask for forgiveness indication.

The choice of trusting the integrity of NFC content when used for implementing security policies, for instance the authenticity of origins saved in the NDEF Id field, or that of the URL path of the browsing context, and then used for same-origin or allowed-origins policy by the user agent, SHOULD be based on prearranged trust relationship (such as encryption and other means), otherwise the integrity of the content MUST NOT be trusted by user agents and security policies MUST NOT be based on this.

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

Security policies

User agents MUST implement the following policies:

  1. Only browsing contexts with a defined origin, whose schema is starting with "https" SHOULD be able to access NFC content. Browsers MAY ignore this rule for development purposes only.
  2. In order to use NFC, the Window object associated with the active Document of the browsing context using the Web NFC API MUST be visible and in focus. This also means that user agents SHOULD make sure the display is on, and the device is unlocked. For web pages in background, receiving and sending NFC content MUST be suspended.

    As a consequence, since every access from a browsing context needs the attention of the user, and since the user must do a physical gesture of tapping the device to another one in order to use NFC, it is assumed in this specification that the user has expressed permission for each NFC operation, provided the other conditions described in this specification are fulfilled.

  3. When sending (i.e. writing or pushing) Web NFC content, the ASCII serialized origin of the browsing context requesting the operation MAY be recorded in each sent NDEF record's NDEF Id field. For details see the sending NFC content algorithm.
  4. When sending (i.e. writing or pushing) Web NFC content, the URL path of the browsing context requesting the operation MUST be recorded in each sent NDEF message's Web NFC record field. For details see the sending NFC content algorithm.
  5. When requesting an NFC adapter by the getAdapter method, or when setting up listeners for reading, or when sending NFC content, the user agent MAY warn the user that physical location may be inferred from the act of using NFC by the origin of the reading browsing context.
  6. Writing Web NFC content to an NFC tag does NOT need to obtain permission, if the NFC tag contains trusted integrity NFC content and the value of the NDEF Id field is equal to the ASCII serialized origin of the writing browsing context. Otherwise the user agent MUST obtain permission for sending NFC content which overwrites existing information. See also the sending NFC content algorithm.
  7. Sending NFC content to an NFC peer does NOT need to obtain permission, but the previous rules apply. See the sending NFC content algorithm.
  8. Making an NFC tag read-only MUST obtain permission, or otherwise fail.
  9. Setting up listeners for reading NFC content SHOULD obtain permission.
  10. The process of reading an NDEF messagedoes NOT need to obtain permission.
  11. For Bluetooth and WiFi handover (supported in later versions), the user SHOULD have to grant access to the secondary API and must be able to properly understand what they are granting.
  12. The payload data on NFC content is untrusted, and MUST NOT be used by the user agent to do automatic handling such as opening a web page with a URL found in an NFC tag, unless the user approves that.
  13. 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 the Web NFC API.

Data Representation

The NFCMessage sequence

The content of any Web NFC message is exposed by the following sequence:

The NFCRecord dictionary

The content of any NDEF record is exposed by the following dictionary:

NFCRecordType kind
USVString type
any data

The kind property MUST return the NFCRecordType of the NDEF record.

The type property MUST return the IANA media type of the NDEF record payload.

The data property MUST return the payload data of the NDEF record with an appropriate ECMAScript type, which depends on the IANA media type.

The NFCRecordType enum

NFCRecordType denotes the data types supported as NDEF record payload in read and send operations in this API.

empty
text
url
json
opaque

The mapping from data types of an NFCRecord to and from NDEF record types is presented in the algorithmic steps which handle the data, i.e. the receiving NFC content algorithm and sending NFC content algorithm.

Data mapping

The mapping from data types of an NFCRecord to NDEF record types, as used in the sending NFC content algorithm is as follows:

NFCRecord kind NFCRecord type NFCRecord data NDEF record type
"empty" not used not used NFC Forum Empty Type (TNF=0)
"text" not used DOMString NFC Forum Well Known Type (TNF=1) with type Text
"url" not used DOMString NFC Forum Well Known Type (TNF=1) with type URI
"json" "application/json", "application/*+json" null or DOMString or Number or Object Media-type as defined in [[RFC2046]] (TNF=2) with associated IANA media type specified in the type attribute.
"opaque" IANA media type ArrayBuffer or typed array Media-type as defined in [[RFC2046]] (TNF=2)
"opaque" "" (empty) ArrayBuffer or typed array NFC Forum External Type (TNF=4)

The mapping from NDEF record types to NFCRecord, as used for incoming NDEF messages described by the receiving NFC content algorithm is as follows:

NDEF record type NFCRecord kind NFCRecord type NFCRecord data
NFC Forum Empty Type (TNF=0) "empty" "" null
NFC Forum Well Known Type (TNF=1) with type Text "text" "text/plain" DOMString
NFC Forum Well Known Type (TNF=1) with type URI "url" "text/plain" DOMString
NFC Forum Well Known Type (TNF=1) with type Smart Poster "url" "text/plain" DOMString
Absolute URI as defined in [[RFC3986]] (TNF=3) "url" "text/plain" DOMString
Media-type as defined in [[RFC2046]] (TNF=2) with associated IANA media type "application/json" or "application/*-json" "json" The IANA media type used in the NDEF record null or DOMString or Number or Object
Media-type as defined in [[RFC2046]] (TNF=2) "opaque" The IANA media type used in the NDEF record ArrayBuffer
NFC Forum External Type (TNF=4) with type other than urn:nfc:ext:w3.org:webnfc* "opaque" "application/octet-stream" ArrayBuffer
Any other NDEF record type "opaque" "application/octet-stream" ArrayBuffer

The Web NFC records MUST NOT be exposed to client browsing contexts.

Extensions to the Navigator interface

The HTML document defines a Navigator interface [HTML] which this specification extends.

readonly attribute NFC nfc

The nfc attribute

When getting the nfc attribute, the user agent MUST return the NFC object, which provides NFC related functionality.

The NFC interface

Promise<NFCAdapter> requestAdapter()

Implementations MAY expose multiple NFC adapters. By using the requestAdapter() method, the browsing context can obtain an adapter object providing NFC functionality. When this method is invoked, the user agent MUST run the following steps:

  1. Let promise be a new Promise object.
  2. Return promise and continue the following steps in parallel.
  3. If the incumbent settings object is not a secure context, then reject promise with "SecurityError", and terminate this algorithm.
  4. If there is no support for NFC adapter handling functionality in hardware, software, or due to physical incompatibility, then reject promise with "NotSupportedError", and terminate this algorithm.
  5. Let adapter be null.
  6. If there is a default NFC adapter, set adapter to the corresponding NFCAdapter object, or if that does not exist, a new NFCAdapter object which is bound to work with the default NFC adapter. Resolve promise with adapter, and terminate these steps.
  7. Otherwise, make a request to the underlying platform to enumerate available NFC adapters. If the request fails, then reject promise with "NotFoundError", and terminate this algorithm.
  8. If the request is successful, then select one of the NFC adapters based on the following algorithm:
    1. Let adapter be a new NFCAdapter object.
    2. If there is only one NFC adapter, then bind adapter to that.
    3. If there are multiple NFC adapters available, and there is a system or user setting available with a preference to select the default adapter, then bind adapter to that.
    4. Otherwise, the user agent MAY pop up a user dialog for selecting one of the NFC adapter, and bind adapter to the selected one.
    5. Otherwise if user prompt is blocked or canceled, select the first built-in NFC adapter.
    6. If no built-in adapters are found, select the first external (e.g. USB) NFC adapter.
    7. Bind adapter to the selected NFC adapter.
  9. Resolve promise with adapter.

The NFCAdapter interface

Promise<void> pushMessage(NFCMessage message, optional NFCPushOptions options)
void cancelPush()
Promise<long> watch(NFCWatchOptions options, MessageCallback callback)
Promise<void> unwatch(long id)

The NFCAdapter interface provides sending Web NFC messages to NFC tags or NFC peers within range, and to set up and cancel NFC watches to handle incoming Web NFC messages either from an NFC tag or an NFC peer.

The NFCPushTarget enum

tag
peer
any

The NFCPushOptions dictionary

NFCPushTarget target
unsigned long timeout

The target property denotes the intended target for the pending pushMessage() operation. The default value is "any".

The timeout property denotes the timeout for the pending pushMessage() operation expressed in milliseconds. The default, and maximal value is 10000, i.e. 10 seconds. After the timeout expires, the message set for sending is cleared, an error is returned, and a new Web NFC message can be set for sending.

The pushMessage() method

The pushMessage() method is used for saving a NDEF message to be sent to an NFC tag for writing, or to an NFC peer device for pushing, next time when they get into proximity range, or until a timeout expires. At any time for there is maximum 2 Web NFC messages that can be set for sending for an origin: one targeted to NFC tags and one to NFC peers. When there is a Web NFC message set for sending to any target, then no more messages are accepted to be set until the current message is sent or a timeout happens.

When the pushMessage(message, options) method is invoked, the user agent MUST run the following sending NFC content algorithm:

  1. Let promise be a new Promise object.
  2. Return promise and continue the following steps in parallel.
  3. If the incumbent settings object is not a secure context, then reject promise with "SecurityError", and terminate this algorithm.
  4. If there is no support for the functionality of sending data to an NFC peer in proximity range, or to write data to an NFC tag, then reject promise with "NotSupportedError", and terminate this algorithm.
  5. Let origin be the origin of the browsing context invoking this method.
  6. Try to obtain permission by applying the following sub-steps:
    • If an expressed permission has been granted before for origin using the Permissions API, then continue with step 6.
    • Otherwise, if a prearranged trust relationship exists, then continue with step 6.
    • Otherwise, try to obtain expressed permission using the Permissions API. If a permissions dialog is involved with the user during this, then the user agent SHOULD notify the user also about that using NFC for sending content may indirectly reveal the physical location of the user in certain conditions. If permission has been granted by the user, then continue with step 6.
    • Otherwise, reject promise with "SecurityError", and terminate this algorithm.
  7. Let options be the second argument.
  8. Let timeout be the value of options.timeout if it is defined, or otherwise 10000 (milliseconds).
  9. Let target be the value of options.target if it is defined, or otherwise "any".
  10. If the message parameter is not a valid non-empty sequence of NFCRecord objects, then reject promise with "SyntaxError", and terminate this algorithm.
  11. Let output be the notation for the NDEF message to be created by an API call to the underlying platform, based on data provided by these steps.
  12. For each NFCRecord record in the sequence message, execute the following steps, or make sure that the underlying platform provides equivalent values to ndef:
    • Let record be the current NFCRecord.
    • Let ndef be the notation for the NDEF record to be created by an API call to the underlying platform.
    • If record.kind is "empty", then execute the following steps:
      • Set the ndef.TNF field to 0 (NFC Empty Type record).
      • Set all the following fields to 0: ndef.TYPE_LENGHT, ndef.ID_LENGTH, ndef.PAYLOAD_LENGTH and thus omit the following fields from the NDEF record: ndef.TYPE, ndef.ID, ndef.PAYLOAD.
      • Reset the NFCMessage output to contain only the current empty record record, and continue with step 11.
    • If record.kind is "text", then execute the following steps, or make sure that the underlying platform provides equivalent values to ndef:

      This is to be used when clients specifically want to write an NDEF Well Known Type Text record. Otherwise clients could also use "opaque" with an explicit IANA media type also for text, which has the advantage of better differentiation, e.g. when using "text/xml", or "text/vcard".

      • If record.data is not of type "string" or "number", then then reject promise with "SyntaxError", and terminate this algorithm.
      • If record.type is not of type "string" or if it does not start with "text/", then reject promise with "SyntaxError", and terminate this algorithm. In addition, user agents MAY check that record.type is a IANA registered media type for text. If not, then the user agent MAY reject promise with "SyntaxError", and terminate this algorithm.
      • Let language be "en". If record.type does include a lang= parameter for language encoding (e.g. "text/plain; lang=fr"), then set language to the language code extracted from record.type. If language is not one of the language codes listed in the IANA language registry (or [[ISO-639.2]]), then user agents MAY reject promise with "SyntaxError", and terminate this algorithm.

        Note that lang= is not standard parameter to IANA media types, but it is used in this specification in order to maintain compatibility with NFC specifications.

      • Otherwise,
        1. Set the ndef.TNF field to 1 (NFC Well Known Type).
        2. Set the def.TYPE field to "T" (value 0x54 in NFC binary encoding).
        3. Set the ndef.PAYLOAD field to record.data encoded according to the [[NFC-STANDARDS]], NFC Forum Text Record Type Definition specification:
          • The first octet is a status byte containing bit flags.
            • If record.type does include a parameter for character set for UTF-8 (e.g. "text/plain; charset=UTF-8;"), then set bit 7 (MSB) to 0 (meaning UTF-8 encoding), otherwise to 1 (meaning UTF-16 encoding).
            • Set bit 6 to 0.
            • Set bits 5 to 0 to the length of language.
          • Set the consecutive octets of ndef.PAYLOAD to the value of language in US-ASCII encoding.
          • Set the consecutive payload octets to record.data in the encoding set by the MSB bit of the first payload octet (by default UTF-16, or UTF-8 on special request).
    • If record.kind is "url", then execute the map URL to NDEF sub-steps, or make sure that the underlying platform provides equivalent values to ndef:
      • If record.data is not of type string, then reject promise with "SyntaxError", and terminate this algorithm.
      • Otherwise,
        • Set the ndef.TNF field to 1 (Well Known Type).
        • Set the ndef.TYPE field to "U" (0x55 in NFC binary encoding).
        • Set the ndef.PAYLOAD field to record.data encoded according to the [[NFC-STANDARDS]], NFC Forum URI Record Type Definition specification: set the first octet according to the applicable scheme abbreviation, and set the rest of the payload bytes to record.data in UTF-8 encoding.
    • If record.kind is "json", then execute the map JSON to NDEF sub-steps, or make sure that the underlying platform provides equivalent values to ndef:
      • If record.data is not of type "string", or "number", or "object", then reject promise with "SyntaxError", and terminate this algorithm.
      • If record.type is not "application/json", or another IANA type for JSON ("application/<type>+json"), then reject promise with "SyntaxError", and terminate this algorithm.
      • Otherwise,
        • Set the ndef.TNF field to 2 (Media Type).
        • Set the ndef.TYPE field to record.type.
        • Set the ndef.PAYLOAD field to record.data according to the [[NFC-STANDARDS]], i.e. as an opaque octet stream.
    • If record.kind is "opaque", then execute the map binary to NDEF sub-steps, or make sure that the underlying platform provides equivalent values to ndef:
      • If record.data is not of instance of ArrayBuffer, then reject promise with "SyntaxError", and terminate this algorithm.
      • The user agent MAY check if record.type is a valid IANA registered type. If not, then MAY reject promise with "SyntaxError", and terminate this algorithm.
      • Otherwise,
        • Set the ndef.TNF field to 2 (Media Type).
        • Set the ndef.TYPE field to record.type.
        • Set the ndef.PAYLOAD field to record.data according to the [[NFC-STANDARDS]], i.e. as an opaque octet stream.
    • Otherwise, if record.kind is undefined, then:
      • If record.data is instance of ArrayBuffer, then set record.type to "application/octet-stream" and execute the map binary to NDEF steps.
      • Otherwise, if type of record.data is "object", then set record.type to "application/json" and execute the map JSON to NDEF steps.
      • Otherwise, if type of record.data is "number" or "string", then set record.type to "plain/text" and execute the map text to NDEF steps.
      • Otherwise reject promise with "SyntaxError", and terminate this algorithm.
    • Add ndef to output.
  13. Add a Web NFC record to output to the end of output by following the write Web NFC record sub-steps, or make sure that the underlying platform provides equivalent values to ndef:
    • Let ndef be the notation for the NDEF record to be created by an API call to the underlying platform.
    • Set ndef.TNF to 4 (NDEF External Type).
    • Set ndef.TYPE to "urn:nfc:ext:w3.org:webnfc".
    • Set ndef.PAYLOAD to the URL path of the browsing context, encoded in UTF-16. This is going to be used by NFC watch filters.

      In future versions a list of "allowed-origins" may be supported. It needs more discussions, since there is a security issue with it. See the Security and Privacy document.

  14. Make a request to the underlying platform to send output to the next device which comes in proximity range, and start a timer timer with timeout. There MUST be exactly one message set for pushing per calling browsing context with exactly one associated timer. This means that every new invocation of the pushMessage() method replaces the previously set push message, and also resets the timer associated with it.
  15. If timer expires, reject promise with "TimeoutError" and terminate this algorithm.
  16. When an NFC device comes in communication range,
    • If target has the value "tag", then the sending should only happen if an NFC tag is tapped, otherwise reject promise "InvalidAccessError" and terminate this algorithm.
    • If target has the value "peer", then the sending should only happen if an NFC peer is tapped, otherwise reject promise with "InvalidAccessError" and terminate this algorithm.
    • If target has the value "any" (which is the default value), then the sending should happen if either an NFC peer or an NFC tag is tapped within the specified timeout.
    • If during the transfer the connection is lost, or an error is signaled by the underlying platform, then reject promise with "NetworkError" and terminate this algorithm.
    • If the transfer is successful, cancel timer and resolve promise.
  17. If timer is still active, and the cancelPush() method is called, reject promise with "AbortError", as described in the cancelPush() algorithm.
  18. If the browsing context loses focus (e.g. the user navigated to another page), then the pending push messages still exist, and timer continues to run until timeout, or until the user switches back the focus and an NFC communication occurs.

The cancelPush() method

The cancelPush method is used for resetting the NDEF message set to be pushed next time an NFC device comes in range.

When the cancelPush() method is invoked, the user agent MUST run the following algorithm:

  1. If the incumbent settings object is not a secure context, then reject promise with "SecurityError", and terminate this algorithm.
  2. If there is no message set for pushing as described in the pushMessage() algorithm, or no active timers associated with it, then terminate this algorithm.

    This step also covers the case when the timer has already fired, which also means that the message buffer is invalid, and is to be replaced by the next invocation of pushMessage().

  3. Otherwise, if there is an active timer associated with a message set to be pushed during the next NFC communication, then execute the following sub-steps:
    • Remove the message set for pushing.
    • Stop and reset the timer associated with messagePush().
  4. Reject the pending promise in the pushMessage() algorithm with "AbortError".

Match patterns

A match pattern is a string which can contain the '*' wildcard character. Match patterns are used primarily for matching IANA media types, for instance the match pattern 'application/*+json' matches 'application/calendar+json', but does not match 'application/json'. The match pattern '*/*json' matches both.

URL patterns

A URL pattern is a URL which can contain '*' characters. Each URL pattern is in the form of

The syntax is the following:

        <url-pattern> := <scheme>://<host><path>
        <scheme> := '*' | 'https'
        <host> := '*' | '*.' <any char except '/' and '*'>+
        <path> := '/' <any chars>
      

Note that '*' has slightly different meaning depending on whether it is in the scheme, host or path part. In a scheme '*' will match only the allowed 'https' scheme. If the host is '*', then it matches any host. If the host is e.g. '*.myhost', then it will match the specified host or any of its subdomains. In the path part, each '*' matches 0 or more characters.

For example, '*://*.mydomain.com/*' will match 'https://services.mydomain.com/myservice1/myapp2/' and 'https://info.mydomain.com/general/'.

The NFCWatchMode enum

web-only
all

The "web-only" value means that only those NDEF messages are exposed which contain a Web NFC record, i.e. which are meant for web pages. This is the default value.

The "all" value means that all NDEF messages are exposed.

The NFCWatchOptions dictionary

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

USVString url
USVString kind
USVString type
NFCWatchMode mode

The url property denotes the URL pattern which is used for matching the URL path of the Web NFC message which is stored in the Web NFC record. The values null, undefined, and "" mean that no matching happens.

The kind property denotes the string value which is used for matching the kind property of each NFCRecord object in a Web NFC message. The values null and undefined mean that no matching happens.

The type property denotes the match pattern which is used for matching the type property of each NFCRecord object in a Web NFC message. The values null and undefined mean that no matching happens. The value "" matches missing type information.

The mode property tells whether only Web NFC content or any NFC content will be watched.

      var watchOptions = {
        url: "www.w3.org/*",  // all paths from the domain are accepted
        kind: "json",
        type: "application/*json"  // all IANA media types dealing with JSON
      }
    
      var watchOptions = {
        url: "*://*/info/restaurant/daily-menu/",  // accepted from any domain
        kind: "opaque",
        type: "application/octet-stream"
      }
    

The watch() method

The watch(options, callback) method enables listening to incoming NDEF messages.

The NFC content to which clients listen can be filtered based on its data type, and based on the URL path of the browsing context which has been saved to the Web NFC record of the NFC content. The latter is matched against URL patterns used in NFC watches.

A NFC watch is referring to a NFCWatchOptions filter saved together the information with NFC adapter it belongs to, and a locally unique identifier which is used for cancellation. The receiving NFC algorithm uses NFC watches to match incoming NFC content.

Multiple consecutive calls to the watch() method from the same origin create filters which are in OR relationship.

Watch filters are grouped by NFC adapter.

When the watch() method is invoked, the user agent MUST run the following NFC watch algorithm:

  1. Let promise be a new Promise object.
  2. Return promise and continue the following steps in parallel.
  3. If the incumbent settings object is not a secure context, then reject promise with "SecurityError", and terminate this algorithm.
  4. If there is no support for the functionality of receiving data from an NFC peer or NFC tag in proximity range, then reject promise with "NotSupportedError", and terminate this algorithm.
  5. Let origin be the origin of the browsing context invoking this method.
  6. If the user has earlier denied permission for origin for all future calls as well, then reject promise with "SecurityError", and terminate this algorithm.
  7. Reading NFC content does not require expressed permission, but unless there is a prearranged trust relationship, user agents SHOULD ask for forgiveness with relevant information displayed to the user which explains that reading NFC content may indirectly reveal the physical location of the user. In addition, if the value of options.mode is "all", then also include in this information that the origin is requesting to read all NFC content, not only those meant for web pages.
  8. If the user has blocked permission from the ask for forgiveness interaction for this origin, then reject promise with "SecurityError", and terminate this algorithm.

    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 user agent to remember these user choices for each origin, regardless of which NFC adapter is used, and consult them on later invocations.

  9. If the first argument options contains invalid values, reject promise with a "SyntaxError", and terminate this algorithm.
  10. If the second argument callback is not a Function, then reject promise with a "SyntaxError", and terminate this algorithm.
  11. If this is the first watch being set up for the current NFC adapter, make a request to the underlying platform to listen to NDEF messages.
  12. If the request fails, then reject promise with "NotSupportedError" , and terminate this algorithm.
  13. Otherwise, let watchId be a locally unique number assigned to options and callback and store them together as an NFC watch.
  14. Resolve promise with watchId.
  15. If the browsing context loses focus (e.g. the user navigated to another page), then the registered watches still SHOULD continue to exist, but SHOULD become paused, i.e. the user agent SHOULD NOT check and use them until the focus is regained.

The unwatch() method

When the unwatch(id) method is invoked, the user agent MUST run the following steps:

  1. Let promise be a new Promise object.
  2. Return promise and continue the following steps in parallel.
  3. If the incumbent settings object is not a secure context, then reject promise with "SecurityError", and terminate this algorithm.
  4. If the parameter id is undefined, then remove all watches and filters set by successive calls of the NFC watch() method on the current NFC adapter.
  5. Otherwise, if the parameter id matches the local identifier of one of the previously set up watches, remove the corresponding watch.
  6. Otherwise, reject promise with "NotFoundError", and terminate this algorithm.
  7. If there are no more watches on the current NFC adapter, then make a request to the underlying platform to stop listening to NDEF messages on that adapter.
  8. Resolve promise.

The algorithm for receiving and parsing NFC content

If there are any NFC watches set up for any NFC adapter, then user agents MUST listen to NDEF messages, according to step 9 of the NFC watch algorithm. When an NDEF message is received by the underlying platform, user agents MUST run the following algorithm:

  1. Let input be the notation for the NDEF message which has been received by the underlying platform.
  2. This is a placeholder for a possible future feature. In this step, implementations MAY check if the origin of the browsing context matches the Web NFC Id of input.If yes, and also prearranged trust relationship exists so that input is trusted integrity NFC content, then same-origin policies MAY be applied.

  3. This is a placeholder for a possible future feature. In this step, implementations MAY check if any of the URL patterns saved in the Web NFC record (in the future) match with the origin of the browsing context. If yes, and also if prearranged trust relationship exists so that input is trusted integrity NFC content, then allowed-origin policies MAY be applied.

  4. Let message be a new empty sequence of NFCRecord objects.
  5. Let messageId be null, used for storing the Web NFC Id of message.
  6. For each NDEF record which is part of input, run the following sub-steps for parsing NDEF record:
    • Let ndef be the notation for the current NDEF record. The fields of ndef are described by the [[NFC-STANDARDS]].
    • Let record be a new NFCRecord object.
    • If ndef.TNF is 0 (NFC Empty Record), then set record.kind to "empty", record.type to "", and record.data to null.
    • If ndef.TNF is 1 (NFC Well Known Type Record), and ndef.TYPE is "T" (value 0x54 in NFC binary encoding), then execute the following sub-steps for parsing NDEF Text record, or make sure that the underlying platform provides equivalent values to the record object properties:
      • Set record.kind to "text".
      • Set record.type to "text/plain".
      • Read the first octet of ndef.PAYLOAD. Let offset be the value given by bits 5 to 0 of the first payload octet.
      • Let language be the string defined by the consecutive offset number of octets, converted from US-ASCII encoding. Append ";lang=" and then the value of language to record.type.
      • Set record.data to the string created from the consecutive ndef.PAYLOAD octets, converted to UTF-16 encoding.
    • If ndef.TNF is 1 (NFC Well Known Type Record), and ndef.TYPE is "U" (value 0x55 in NFC binary encoding), then execute the following sub-steps for parsing NDEF URL record, or make sure that the underlying platform provides equivalent values to the record object properties:
      • Set record.kind to "url".
      • Set record.type to "text/plain".
      • Let scheme be the value of the first octet of ndef.PAYLOAD.
      • If scheme is not 0, then set record.data to the string obtained from mapping the value of scheme to the URL scheme as specified in the [[NFC-STANDARDS]] URI Record Type Definition specification, Section 3.2.2.
      • Set record.data to the UTF-16 string converted from the octets of ndef.PAYLOAD except the first octet.
    • If ndef.TNF is 3 (NFC Absolute URI Type record), then set record.kind to "url", set record.type to "text/plain" and set record.data to the string converted from ndef.PAYLOAD.
    • If ndef.TNF is 2 (NFC Media Type record), then execute the following sub-steps for parsing NDEF Media record, or make sure that the underlying platform provides equivalent values to the record object properties:
      • If ndef.TYPE matches the match pattern "application/*json", then
        • Set record.kind to "json".
        • Set record.type to ndef.TYPE.
        • Set record.data to the result of converting ndef.PAYLOAD to string.

          The payload SHOULD NOT be evaluated by user agents for security reasons.

      • Otherwise,
        • Set record.kind to "opaque".
        • Set record.type to ndef.TYPE.
        • Set record.data to a new ArrayBuffer object constructed from the octets of ndef.PAYLOAD.
    • If ndef.TNF is 4 (NFC External Type record), and ndef.TYPE is urn:nfc:ext:w3.org:webnfc, then set messageId to the value decoded from ndef.PAYLOAD in UTF-16.
    • Otherwise, if ndef.TNF is 4 (NFC External Type record), or 5 (NFC Unknown Type record) then execute the following sub-steps, or make sure that the underlying platform provides equivalent values to the record object properties:
      • Set record.kind to "opaque".
      • If ndef.TYPE is defined, then set record.type to that string value, otherwise to "application/octet-stream.
      • Set record.data to a new ArrayBuffer object constructed from the octets of ndef.PAYLOAD.
    • Add record to message.
  7. For matching message against the registered NFC watches, for each NFC watch watch that has been registered using the watch() method, execute the following sub-steps:
    • Let options be the NFCWatchOptions saved with the watch, and let callback be the registered callback function.
    • If options.mode is "web-only", and messageId is null, then skip to the next NFC watch.
    • Otherwise, if options.mode is "web-only", and messageId is not null, or if options.mode is "all", then execute the following sub-steps:
      • If options.url is defined, and if messageId does not match the URL pattern stored in options.url, then skip to the next NFC watch.
      • If options.kind is defined, and it is not equal to record.kind, then skip to the next NFC watch.
      • If options.type is defined, and it is not equal to options.type, then skip to the next NFC watch.
      • Otherwise, invoke the function callback with record passed as first argument, and messageId passed as second argument.

Changes

The following is a list of substantial changes to the document. For a complete list of changes, see the change log on Github. You can also view the recently closed bugs.

Open issues

The following problems are being discussed and need most attention:

This version addresses the issues above, and also other issues.

Acknowledgements

The editors would like to express their gratitude to the former editors Luc Yriarte and Samuel Ortiz, and also to Don Coleman, Anne van Kesteren, Domenic Denicola, Jonas Sickling, Jeffrey Yasskin, Alexander Shalamov, Salvatore Iovene, and Rijubrata Bhaumik for their technical guidance, implementation feedback and support.