Web NFC API

Draft Community Group Report

Latest editor's draft:
https://w3c.github.io/web-nfc/
Editors:
Kenneth Rohde Christiansen ( Intel )
Zoltan Kis ( Intel )
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 deined in NFC Forum Technical Specifications .

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

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. Terminology and conventions

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

2.2 NFC specific terms

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 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 .

An NDEF message encapsulates one or more application-defined NDEF record s. 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 .

2.3 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 Web NFC message consists of a sequence of NDEF record s.

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 MB field (bit 7 , message begin) indicates whether this is the beginning of a message, the ME field (bit 6 , message end) indicates whether it is the end. The CF field (bit 5 , chunk flag) indicates whether the payload is chunked across multiple records.

Note

Web NFC turns all chunked records into logical records.

The SR field (bit 4 , short record) indicates whether the record is a short record. A short record is 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 IL field (bit 3 , id length) indicates whether an ID LENGTH field is available. This optional identifier is a URL.

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

Other fields include TYPE LENGTH field , TYPE field , ID LENGTH field , ID field , PAYLOAD LENGTH field and the PAYLOAD field .

Note

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

2.4 Record types

2.4.1 Empty NDEF records (TNF 0)

The empty record s, which have no payload or type and are used to indicate empty tags.

2.4.2 Well-known records (TNF 1)

The NFC Forum has standardized a small set of useful RTD (Record Type Definition) types for use in the NFC Forum well-known type record s, 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 (containing optional embedded records for url, text, signature and actions), and handover records. Most of these are defined in NFC Record Type Definition (RTD) Technical Specification .

For well-known records, the RTD type is stored in the TYPE field and is " T " ( 0x54 ) for text, " U " ( 0x55 ) for url and " Sp " ( 0x53 , 0x70 ) for smart poster.

Other known RTD types supported by the platform and not Web NFC are " ac " ( 0x61 , 0x63 ) for alternative carrier, " Hc " ( 0x48 , 0x63 ) for handover carrier, " Hr " ( 0x48 , 0x72 ) for handover request, and " Hs " ( 0x48 , 0x73 ) for handover select.

An NFC handover defines RTD 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.

Smart poster embeds additional records inside its payload. Below you see an example embedding a text and a url record.

2.4.3 MIME type records (TNF 2)

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

Note

Web NFC has special handling for working with JSON MIME type data.

2.4.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.

2.4.5 External type records (TNF 4)

The NFC Forum external type record s are for client specified data and must have a type name following the NFC Record Type Definition (RTD) Technical Specification standard.

Note Web NFC defines a special external type record that is not accessible to client applications.

2.4.6 Web NFC author records (TNF 4) When writing data with Web NFC, a special author type record is written in addition to the other records. This record is specificed by this specification and is specific to Web NFC. The record indicates that the containing NDEF message is targeted for browsing context s using this API and contains information useful for handling the NDEF message with the algorithms defined in this specification. The format is as follows: A short, non-chunked record with IL field set to 0 and thus no ID LENGTH field and ID field . Uses NFC Forum external type record with the TYPE field set to " w3.org:A ". The payload contains the message identifier of the Web NFC message . This enables matching Web NFC content with URL pattern s specified by NFCReader s. For NDEF message s that are not Web NFC message s, the message identifier is null . The term Web NFC content denotes all Web NFC message s contained within an NDEF message , identified by the message identifier . This version of the specification supports one author type record per NDEF message . Note As part of the NDEF record , an ID field may be present in each record for application specific usages. According to the NFC Forum Technical Specifications it contains a URL with the maximum length of 256 bytes. This URL is used for identifying the NDEF record payload in an application specific way.

2.4.7 2.4.6 Unknown type records (TNF 5)

The unknown record s are records that store opaque data without associated MIME type .

2.4.8 2.4.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.

First record:
Intermediate record:
Last record:

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

3. Introduction

This section is non-normative.

In general, there are following 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 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.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 implementors.

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 contract 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. Communiction 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 require 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.

Note

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.

4. Examples

This section is non-normative.

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

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 a Web NFC message , when the Document of the top-level browsing context using the Web NFC API is visible and focused . 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 Web NFC message , when the Document of the top-level browsing context using the Web NFC API is visible and focused .
  3. Reading an NFC tag when no Document using the Web NFC API is visible or focused .
    Note

    This use case is not supported in this version of the specification, and it has low priority for future versions as well.

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 Web NFC message with a different message record identifier (i.e. overwriting a web-specific tag).
  3. Writing to an NFC tag which already contains a Web NFC message with the same message 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 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 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 and focused with active NFCReader , then the content is delivered to the page through the NFCReadingEvent .

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 payments 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 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.

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 Web NFC message s.
  4. Allow users to write a payload via NDEF record s to compatible devices, such as writeable tags, when they come in range, as Web NFC 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 the Web NFC API can handle:

7. 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.

7.1 Chain of trust

Web pages using the Web 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 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 message record identifier , unless a prearranged trust relationship exists.

7.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:

7.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.

7.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.

7.4.1 Secure Context

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

7.4.2 Visible and focused document

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

To determine if a given document is visible and focused the user agent MUST run the following steps:

  1. If the currently focused area does not belong to document , return false.
  2. If document 's visibilityState is "hidden", return false.
  3. Return true.

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 .

7.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 §  9.9 Writing or pushing content section.

Pushing Web NFC content an NDEF message to an NFC tag does not need to obtain permission , if the existing NDEF message identifier host of the author type only contains NDEF record on that NFC tag s without ID field is equal to s, or with ID field s matching the serialized host 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 §  9.9 Writing or pushing content section.

Issue 1
Verify with security folks.

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.

7.4.4 Record Store site URL host and path as record identifier when pushing writing data

When pushing Web NFC content an NDEF message , the registrable domain , serialized host and the URL path , of the current settings object when requesting the operation must be recorded stored as the record identifier in each sent top-level NDEF message 's author type record Record . For details see the §  9.9 Writing or pushing content section.

7.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.

7.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.

8. Data Representation

8.1 The NDEFMessage interface

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

[Exposed=Window]
interface NDEFMessage {
  
  readonly attribute

  constructor(NDEFMessageInit messageInit);
  readonly attribute FrozenArray<NDEFRecord> records;
};
dictionary 
  

dictionary NDEFMessageInit {

  sequence<NDEFRecordInit> records;
};

The url property represents the message identifier of a received Web NFC message . The records property represents a list of NDEF record s defining the Web NFC message .

The NDEFMessageInit dictionary is used to initialize a Web NFC message . When used in the NFCWriter.push() method, its url member represents a URL path used for constructing the message identifier of the pushed Web NFC content .

8.2 The NDEFRecord interface

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

typedef any NDEFRecordData;
[Exposed=Window]
interface NDEFRecord {
  constructor(NDEFRecordInit recordInit);
  readonly attribute NDEFRecordType recordType;
  readonly attribute USVString mediaType;
  readonly attribute USVString id;
  USVString? toText();
  [NewObject] ArrayBuffer? toArrayBuffer();
  [NewObject] any toJSON();
  sequence<NDEFRecord> toRecords();
};
dictionary NDEFRecordInit {
  NDEFRecordType recordType;
  USVString mediaType;
  USVString id;
  NDEFRecordData 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 NDEFRecordData is a union type representing data types allowed for NDEFRecordInit.data property.

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 message 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 toText() method, when invoked, MUST return the result of running convert NDEFRecord.[[PayloadData]] bytes with an NDEFRecord object and a text type.

The toArrayBuffer() method, when invoked, MUST return the result of running convert NDEFRecord.[[PayloadData]] bytes with an NDEFRecord object and an arrayBuffer type.

The toJSON() method, when invoked, MUST return the result of running convert NDEFRecord.[[PayloadData]] bytes with an NDEFRecord object and a JSON type.

The toRecords() method, when invoked, MUST return the result of running convert NDEFRecord.[[PayloadData]] bytes with an NDEFRecord object and an external type.

The NDEFRecordInit dictionary is used to initialize an NDEF record with its type, optional MIME type and message identifier, record identifier , and payload data via the members of recordType , mediaType , id , and data . 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 §  9.11 Receiving and parsing content and §  9.9 Writing or pushing content sections.

To convert NDEFRecord.[[PayloadData]] bytes , pass a record and a type , run these steps:

  1. Let bytes be record . [[PayloadData]] .
  2. Let recordType be the value of record 's recordType attribute.
  3. Switch on type :
    text
    1. If the recordType value is equal to " empty ", return null .
    2. If the recordType value is equal to " text ", then run the following sub-steps:
      1. Let header be the first byte of bytes .
      2. Let charset be " utf-8 " if bit 7 ( MB field ) of header is equal to the value 0, or else " utf-16be ".
      3. Let offset be the value given by bit 5 to bit 0 of the header .
      4. Let buffer be the bytes , from position offset + 1 to the end.
      5. If charset is equal to " utf-8 ", return the result of running UTF-8 decode on buffer .
      6. Otherwise, return the result of running decode on buffer with encoding set to " utf-16be ".
    3. Otherwise, return the result of running UTF-8 decode on bytes .
    arrayBuffer
    1. If the recordType value is equal to " json " or " opaque ", then return an ArrayBuffer whose contents are the bytes . Re- throw any exceptions.
    2. Otherwise, return null .
    JSON
    1. If the recordType value is equal to " json " or " opaque ", then return the result of running parse JSON from bytes on bytes . Re- throw any exceptions.
    2. Otherwise, return null .
    external
    1. If the recordType value is an external type , then return the result of running parse records from bytes on bytes .
    2. Otherwise, return null .

8.3 The NDEFRecordType string

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


typedef


DOMString




NDEFRecordType


;

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

The " empty " string
The value representing empty NDEFRecord .
The " text " string
The value representing NDEFRecord of a text type.
The " url " string
The value representing NDEFRecord of a url type.
The " smart-poster " string
The value representing NDEFRecord of a smart-poster type.
The " json " string
The value representing NDEFRecord of a json type.
The " opaque " string
The value representing NDEFRecord of an opaque type.
An external type
A DOMString representing a custom type for the external type record . The type must follow the external type 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:A w3.org:member ". And additional ABNF exists for well-known type record s:

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

Note

The NFC Record Type Definition (RTD) Technical Specification defines every type in the well-known type record s 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.

8.4 Data mapping

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

NDEFRecordInit recordType NDEFRecordInit mediaType NDEFRecordInit data NDEF record type
" empty " unused unused Empty record
" text " unused DOMString Well-known type record with type " T "
" url " unused DOMString Well-known type record with type " U "
" json " JSON MIME type JSON type MIME type record with type equal to MIME type .
" opaque " MIME type ArrayBuffer MIME type record
external type unused ArrayBuffer or
any typed array type
External type record

The mapping from NDEF record types to NDEFRecord , as used for incoming NDEF message s described in the §  9.11 Receiving and parsing content section, is as follows:

NDEF record type NDEFRecord recordType NDEFRecord mediaType NDEFRecord data getters
Empty record " empty " empty toText() or
toJSON() or
toArrayBuffer()
Well-known type record with type " T " " text " " text/plain " toText()
Well-known type record with type " U " " url " " text/plain " toText()
Well-known type record with type " Sp " " smart-poster " "" toRecords() or
toArrayBuffer()
Absolute-URL record " url " " text/plain " toText()
MIME type record with JSON MIME type " json " The MIME type used in the NDEF record toText() or
toJSON() or
toArrayBuffer()
MIME type record " opaque " The MIME type used in the NDEF record toText() or
toJSON() or
toArrayBuffer()
External type record with type other than w3.org:A external type " application/octet-stream " toText() or
toJSON() or
toArrayBuffer()
Any other NDEF record type " opaque " " application/octet-stream " toText() or
toJSON() or
toArrayBuffer()
The author type record s MUST NOT be exposed to client browsing context s.

9. The NFCReader and NFCWriter objects

The objects provide a way for the browsing context to use NFC functionality. They allow for pushing Web NFC message s to NFC tag s or NFC peer s within range, and to act on incoming Web NFC message s either from an NFC tag or an NFC peer .
typedef (DOMString or ArrayBuffer or NDEFMessageInit) NDEFMessageSource;
[SecureContext, Exposed=Window]
interface NFCWriter {
  constructor();
  Promise<void> push(NDEFMessageSource message, optional NFCPushOptions options={});
};
[SecureContext, Exposed=Window]
interface NFCReader : EventTarget {
  constructor();
  attribute EventHandler onreading;
  attribute EventHandler onerror;
  void scan(optional NFCScanOptions options={});
};
[SecureContext, Exposed=Window]
interface NFCReadingEvent : Event {
  constructor(DOMString type, NFCReadingEventInit readingEventInitDict);
  readonly attribute DOMString serialNumber;
  [SameObject] readonly attribute NDEFMessage message;
};
dictionary NFCReadingEventInit : EventInit {
  DOMString? serialNumber = "";
  required NDEFMessageInit message;
};
[SecureContext, Exposed=Window]
interface NFCErrorEvent : Event {
  constructor(DOMString type, NFCErrorEventInit errorEventInitDict);
  readonly attribute DOMException error;
};
dictionary NFCErrorEventInit : EventInit {
  required DOMException error;
};

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

The NFCReadingEvent 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.

NFCReadingEventInit 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 NFCErrorEvent is the event being dispatched on errors, with the DOMException object as the error attribute.

NFCErrorEventInit is used in order to initialize a new event with a DOMException data via the error member.

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

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

A NFCReader object has the following internal slots :

Internal Slot Description ( non-normative )
[[Url]] [[Id]] This slot holds the provided NFCScanOptions . url id value. It is initially an empty string .
[[RecordType]] This slot holds the provided NFCScanOptions . recordType value. It is initially unset.
[[MediaType]] This slot holds the provided NFCScanOptions . mediaType value. It is initially an empty string .
[[Signal]] This slot holds the provided NFCScanOptions . signal value. It is initially unset.

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.

9.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 Description ( non-normative )
[[Suspended]] A boolean flag indicating whether NFC functionality is suspended or not, initially false .
[[ActivatedReaderList]] A set of NFCReader instances initially set to the empty set .
[[PendingPush]] A promise-writer tuple where the promise holds a pending Promise and writer holds a NFCWriter . Initially the slot is empty.

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.

9.2 Handling NFC adapters

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

9.3 Handling Window visibility and focus

Each Window object where the Web NFC API is exposed has separate NFCWriter and NFCReader instances. The visible and focused state of the the top-level browsing context 's Document determines the suspended state of the associated NFCWriter and NFCReader instances.

The term suspended in this specification refers to NFC operations being suspended, i.e. no NFC content is pushed by NFCWriter s, and no received NFC content is presented to any NFCReader while suspended. However, platform level timers for the NFCWriter.push() method continue running, and if they expire, the event should be recorded and handled when execution next resumes, i.e. when the focus event is fired on the Window object.

When the Document of the top-level browsing context using the Web NFC API is visible and focused , resume NFC . Otherwise, suspend NFC .

9.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. Let writer be tuple 's writer.
  3. Let p be tuple 's promise.
  4. Stop the writer 's timer if it is active.
  5. If the writer has already initiated NFC data transfer, abort these steps.
  6. Clear the pending push tuple .
  7. Reject p with an " AbortError " DOMException and abort these steps.

9.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 .

9.6 The NFCPushOptions dictionary

dictionary NFCPushOptions {
  NFCPushTarget target = "any";
  unrestricted double timeout = Infinity;
  boolean ignoreRead = true;
  AbortSignal? signal;
};

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

The timeout property denotes the timeout for the pending push() operation expressed in milliseconds. The default value is implementation-dependent. The value Infinity means there is no timeout, i.e. no timer is started. After the timeout expires, the message set for pushing is cleared, an error is returned, and a new Web NFC message can be set for pushing.

When the value of the ignoreRead property is true , the push algorithm will skip invoking the receiving and parsing steps for an NFC tag .

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

9.7 The NFCPushTarget enum

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

enum NFCPushTarget {
  "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 .

9.8 The NFCScanOptions dictionary

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

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

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

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

The recordType property denotes the enum value which is used for matching the recordType property of each NDEFRecord object in a Web NFC 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 a Web NFC message . The default value "" means that no matching is performed.

Example 10 : Filter accepting only JSON content from https://www.w3.org
const options = {
  

  id: "https://www.w3.org/*",  // any path from the domain is accepted
  recordType: "json",
  mediaType: "application/*+json"  // any JSON-based MIME type
}

Example 11 : 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/",
  recordType: "opaque",
  mediaType: "application/octet-stream"
}

9.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 at maximum of two Web NFC 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, a timeout happens, or the push is aborted.

9.9.1 The push() method

The NFCWriter.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. Let signal be the options ’ dictionary member of the same name if present, or null otherwise.
  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 pushing data is not supported by the underlying NFC Adapter , then reject p with a " NotSupportedError " DOMException and return p .
  8. If signal ’s aborted flag is set, then reject p with an " AbortError " DOMException and return p .
  9. If signal is not null , then add the following abort steps to signal :
    1. If the instance has already initiated NFC data transfer, and it can't be aborted, ignore the abort signal and return.
    2. Stop the instance's timer if it is active.
    3. Reject p with an " AbortError " DOMException and abort these steps.
  10. Run the following steps in parallel :
    1. An implementation MAY reject p with a " NotSupportedError " DOMException and abort these steps.
      Note
      The UA might terminate message push at this point. The reasons for terminations 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 operation requested.
    2. Let target be options 's target.
    3. Let timeout be options 's timeout.
    4. If the message parameter is not of type defined by the NDEFMessageSource union, reject p with a TypeError , and abort these steps.
    5. If the message parameter is of NDEFMessageInit type, and message 's records is empty , reject p with a TypeError and abort these steps.
    6. If timeout value is NaN or negative, reject p with a TypeError and abort these steps.
    7. If timeout value is not supported by the UA, reject p with a " NotSupportedError " DOMException and abort these steps.
    8. Let output be the notation for the NDEF message to be created by UA, as the result of passing message to create Web NFC message . If this throws an exception, reject p with that exception and abort these steps.
    9. If target is " any ", run the following steps twice, once with slot set to the value " tag ", and once set to the value " peer "; otherwise run the following step once, with slot set to the value of target .
    10. Attempt to abort a pending push operation .
    11. Associate output with slot .
    12. If timeout value is not equal to Infinity , start a timer timer with the timeout value set to timeout .
    13. Add the following async write handlers :
      The timer expires
      1. Reject p with " TimeoutError " DOMException .
      An NFC device device comes within communication range
      1. Verify the following conditions: In case of success, run the following sub-steps:
        1. Stop timer if active.
        2. If device is an NFC tag ,
        3. Initiate data transfer to device using output as buffer, using the NFC adapter in communication range with (connected to) device .
        4. If the transfer fails, reject p with " NetworkError " DOMException and abort these steps.
          Note

          Multiple adapters should be used sequentially by users. There is very small 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.

        5. When the transfer has completed, clear output associated with target , resolve p .
    14. Let transformedPromise be the result of transforming React to p :
      1. If p with a fulfillment and rejection handler that: was settled (fulfilled or rejected), then:
        1. Clears the pending push tuple .
        2. Removes async write handlers .
    15. Set pending push tuple to ( this , transformedPromise p ).
    16. Return transformedPromise p .
    Note

    If NFC is suspended , continue waiting until timer expires (if set), or promise is aborted by the user, or until an NFC device comes within communication range.

9.9.1.1 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 2

      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 .

9.9.1.2 Creating Web NFC message

To create Web NFC message given a message run these steps:

  1. Let output be the notation for the NDEF message to be created by the UA as a result of these steps.
  2. 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, if the type of record 's data is an ArrayBuffer , then set record 's recordType to " opaque ".
      4. Otherwise, set record 's recordType to " json ".
    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 "
      " json "
      " opaque "
      external type
      unmatched type
    3. If message 's id is not empty: null :
    4. Add ndef to output .
  3. Let authorRecord be the result of invoking create an author type record given message 's url. If this throws exception e , reject promise with e and abort these steps. Add authorRecord to output . Note Implementations may choose the location of the author type record within the NDEF message .
9.9.1.3 Mapping empty record to NDEF

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

  1. Let ndef be the notation for the NDEF record to be created by the UA.
  2. Set the ndef 's TNF field to 0 ( empty record ).
  3. Set the ndef 's IL field to 0 .
  4. Set ndef 's TYPE LENGTH field , and PAYLOAD LENGTH field to 0 , and omit TYPE field and PAYLOAD field .
  5. Return ndef .

9.9.1.4 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 " opaque " with an explicit MIME type text type, which allows for better differentiation, e.g. when using " text/xml ", or " text/vcard ".

  1. If the type of a record 's data is not a DOMString , 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 " text ", and subtype is " plain ".
    2. If mimeTypeRecord 's type is not " text ", then throw a " SyntaxError " DOMException and abort these steps.
  3. Let language be mimeTypeRecord 's parameters[" lang "] if it exists , or " en ".
  4. Let charset be mimeTypeRecord 's parameters[" charset "] if it exists , or " utf-8 ".
  5. If charset is not equal to " utf-8 ", throw a TypeError .
  6. Let header be a byte constructed the following way:
    1. Set bit 7 to the value 0 (meaning UTF-8 encoding ).
    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 .
  7. 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. Let stream be the resulting byte stream of running UTF-8 encode on record 's data.
    4. Read bytes from stream into data (from position languageLength + 1) until read returns end-of-stream .
  8. Set length to the length of data .
  9. 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 .
  10. Return ndefRecord .

Note

The lang= parameter is a non-standard parameter to MIME type s, but it is used in this specification in order to maintain compatibility with NFC Forum Technical Specifications .

9.9.1.5 Mapping URL to NDEF

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

  1. If record 's data is not a DOMString , throw a TypeError and abort these steps.
  2. Let url be the result of parsing record 's data.
  3. If url is failure, throw a TypeError and abort these steps.
  4. Let serializedURL be serialization of url .
  5. Match the URI prefixes as defined in NFC Forum Technical Specifications , URI Record Type Definition specification, Section 3.2.2, against the serializedURL .
  6. Let prefixString be the matched prefix or else the empty string .
  7. Let prefixByte be the corresponding prefix number, or else 0 .
  8. Let shortenedURL be serializedURL with prefixString removed from the start of the string .
  9. 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 .
  10. Set length to the length of data .
  11. 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 .
  12. Return ndefRecord .

9.9.1.6 Mapping JSON to NDEF

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

  1. 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 " json ".
    2. If mimeTypeRecord is not a JSON MIME type , then throw a " SyntaxError " DOMException and abort these steps.
  2. Let data be an empty byte sequence .
    1. Let stream be the resulting byte stream of executing serialize JSON to bytes on record 's data.
    2. Read bytes from stream into data until read returns end-of-stream .
  3. Set length to the length of data .
  4. 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 .
  5. Return ndefRecord .

Note
9.9.1.7 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 an ArrayBuffer , 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 .

9.9.1.8 Mapping external data to NDEF

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

  1. If the type of a record 's data is not an ArrayBuffer , throw a TypeError and abort these steps.
  2. Issue 2 3
    In addition to supporting ArrayBuffer, we need to support sub records. That is really what makes external records interesting.
  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 .

9.9.1.9 Creating an author type record To create an author type record given URL path urlPath , run these steps: Let ndef be the notation for the NDEF record to be created by the UA. Set ndef 's SR field to 1 (short record). Set ndef 's IL field to 0 (no ID LENGTH field and ID field ). Set ndef 's CF field to 0 (no chunked record). Set ndef 's TNF field to 4 ( external type record ). Set ndef 's TYPE field to " w3.org:A ". Set ndef 's PAYLOAD to the result of invoking create a message identifier given urlPath . If this throws an exception, re- throw it. Return ndef . 9.9.1.10 Creating a message record identifier

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

  1. Let origin be the current settings object 's origin.
  2. Let author host be origin 's host, serialized .
  3. Append urlPath to author . Let urlRecord be the result of parsing author id with " https:// " prepended. + host as the base URL.
  4. If urlRecord is failure, any of the following cases matches, throw a TypeError and abort these steps. 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 author identifier .

9.10 Listening for content

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

Each NFCReader can filter the NFC content accept NDEF message s based on data type, and the URL path of the browsing context which has been saved to the author type a record of the NFC content . identifier (URL) filters.

If you filter Filtering by a record identifier URL path , that pattern, means that it will be matched against the author type URLs found in the NDEF record s' ID field , thus the presence of such is required. If you don't filter by URL path , then all NFC devices are accepted. The latter is matched against the URL pattern s associated with the activated reader objects .

9.10.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.

9.10.2 URL patterns

A URL pattern is a URL record that can be used to match the message optional record identifier of a Web NFC message 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 message record identifier
host exact match or ends with ( URL pattern 's host prepended with " . ").
path If URL pattern 's path is " /* ", match any message 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.

9.10.3 URL pattern match algorithm

To match message record identifier with URL pattern for a given message record identifier and URL pattern , run these steps:
  1. Let raw id be a message 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 author id 's host does not end with subdomain pattern and author id 's host is not equal to pattern 's host , return false .
  10. If pattern 's path is equal to " /* ", return true .
  11. If author id 's path begins with pattern 's path , return true .
  12. Otherwise, return false .

9.10.4 The scan() method

The section §  9.11 Receiving and parsing content uses NFCReader instances to match incoming NFC content .

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

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

  1. Let reader be the NFCReader instance.
  2. Let options be first argument.
  3. For each key value of options :
    1. If key equals " signal ", set reader . [[Signal]] to value .
    2. Otherwise, if key equals " url id ", set reader . [[Url]] [[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 .
  4. If there is no underlying NFC Adapter , or if a connection cannot be established, then
    1. Let e be the result of create a " NotSupportedError " DOMException .
    2. Fire an event named " error " at reader using NFCErrorEvent with its error attribute initialized to e .
    3. Return.
  5. If the UA is not allowed to access the underlying NFC Adapter (e.g. a user preference), then
    1. Let e be the result of create a " NotReadableError " DOMException .
    2. Fire an event named " error " at reader using NFCErrorEvent with its error attribute initialized to e .
    3. Return.
  6. If reader . [[Signal]] 's aborted flag is set, then return.
  7. If reader . [[Signal]] is not null , then add the following abort steps to reader . [[Signal]] :
    1. Remove the NFCReader 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.
  8. Run the following steps in parallel :
    1. If the obtain reading permission steps return false , then
      1. Let e be the result of create a " NotAllowedError " DOMException .
      2. Fire an event named " error " at reader using NFCErrorEvent with its error attribute initialized to e .
      3. Return.
    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 run the following sub-steps:
      1. Let e be the result of create a " NotSupportedError " DOMException .
      2. Fire an event named " error " at reader using NFCErrorEvent with its error attribute initialized to e .
      3. Return.
    4. If the reader . [[Url]] [[Id]] is not an empty string and it is not a valid URL pattern , then
      1. Let e be the result of create a " SyntaxError " DOMException .
      2. Fire an event named " error " at reader using NFCErrorEvent with its error attribute initialized to e .
      3. Return.
    5. Add reader to the activated reader objects .
    6. If the Document of the top-level browsing context is not visible and focused (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 and focused again.

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 .

9.11 Receiving and parsing content

If there are any NFCReader instances in activated reader objects then UAs MUST listen to NDEF message s, according to step 3 of the NFC listen algorithm .

9.11.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 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, we ignore bit 5 ( CF field ).
      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 .

9.11.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. If ndef 's typeNameField is 0 ( empty record ), then set record 's recordType to " empty " and set record 's mediaType to "" .
  3. 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 )
  4. 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.
  5. If 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 .
  6. If ndef 's typeNameField is 4 and ndef 's lowercased TYPE field is " w3.org:a " ( author type record ), then set message 's url to the ndef 's payload . 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.
  7. 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.

9.11.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|s mediaType to mimeType , 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 mimeType 's parameters[" lang "] to language .
  8. Set record 's mediaType to the result of serialize a MIME type with mimeType as the input.
  9. Let buffer be the byte sequence of ndefRecords 's PAYLOAD field .
  10. Set record . [[PayloadData]] to buffer .
  11. return record .

Note

Using the encoder , it is only possible to encode as UTF-8, unless you do the encoding manually and use the " opaque " recordType , which allows you to write any opaque data.

When you write a string to the " text " recordType , it will be written as UTF-8. External applications have the ability to additionally encode this field as UTF-16BE, but that is transparent from the use of the NFCReader which will always return the data as a string .

As external applications may have encoded the " opaque " recordType using a different encoding, which can be decoded using Encoding Standard if you know the encoding.

9.11.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. Set record 's mediaType to " text/plain ".
  3. If ndefRecord 's PAYLOAD field is not present, set record . [[PayloadData]] to undefined and return record .
  4. Let buffer be the byte sequence of ndefRecords 's PAYLOAD field .
  5. Let prefixByte be the value of the first byte of buffer .
  6. 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 .
  7. Otherwise, if there is no match for prefixByte , set record . [[PayloadData]] to buffer .
  8. return record .

9.11.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. Set record 's mediaType to "".
  3. If ndefRecord 's PAYLOAD field is not present, set record . [[PayloadData]] to undefined and return record .
  4. Let buffer be the byte sequence of ndefRecords 's PAYLOAD field .
  5. Set record . [[PayloadData]] to buffer .
  6. return record .

9.11.6 Parsing NDEF MIME type records

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

  1. Let mimeType be the MIME type returned by running parse a MIME type on ndefRecord 's TYPE field .
  2. If mimeType is a JSON MIME type , then
    1. Set record 's recordType to " json ".
    2. Set record 's mediaType to the result of serialize a MIME type with mimeType as the input.
  3. Otherwise,
    1. Set record 's recordType to " opaque ".
    2. Set record 's mediaType to the result of serialize a MIME type with mimeType as the input.
  4. Let buffer be the byte sequence of ndefRecords 's PAYLOAD field if that exists, or otherwise undefined .
  5. Set record . [[PayloadData]] to buffer .
  6. return record .

9.11.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 " url ".
  2. Set record 's mediaType to " text/plain ".
  3. Let buffer be the byte sequence of ndefRecords 's TYPE field .
  4. return record .

9.11.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. Set record 's mediaType to " application/octet-stream ".
  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 .

9.11.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 " opaque ".
  2. Set record 's mediaType to " application/octet-stream ".
  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 .

9.11.10 The NFC reading algorithm

When the UA is to receive NFC content it MUST run the following algorithm:
Note

The UA SHOULD represent an unformatted NFC tag as an NDEF message containing a single empty NDEF record .

  1. If NFC is suspended , abort these steps.
  2. Let message be a new NDEFMessage object, with message 's url set to null and message 's records set to the empty list .
  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 input be the notation for the NDEF message which has been received.
  6. 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.
  7. If NFC is not suspended and message 's records is not empty , run the dispatch NFC content steps with given serialNumber and message .

9.11.11 Dispatching NFC content

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

  1. For each NFCReader instance reader in the activated reader objects , run the following sub-steps:
    1. Let match be the result of running URL pattern match , with If reader . [[Url]] [[Id]] as the URL pattern is present and message doesn't match any record 's url as the message identifier . If match id where record is false , an element of message , continue .
    2. If reader . [[RecordType]] is present and it is not equal to any record .[[RecordType]] '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 NFCReadingEvent with its serialNumber attribute initialized to serialNumber and message attribute initialized to message .

A. IDL Index

[Exposed=Window]
interface NDEFMessage {
  
  readonly attribute

  constructor(NDEFMessageInit messageInit);
  readonly attribute FrozenArray<NDEFRecord> records;
};
dictionary 
  

dictionary NDEFMessageInit {

  sequence<NDEFRecordInit> records;
};
typedef any NDEFRecordData;
[Exposed=Window]
interface NDEFRecord {
  constructor(NDEFRecordInit recordInit);
  readonly attribute NDEFRecordType recordType;
  readonly attribute USVString mediaType;
  readonly attribute USVString id;
  USVString? toText();
  [NewObject] ArrayBuffer? toArrayBuffer();
  [NewObject] any toJSON();
  sequence<NDEFRecord> toRecords();
};
dictionary NDEFRecordInit {
  NDEFRecordType recordType;
  USVString mediaType;
  USVString id;
  NDEFRecordData data;
};
typedef DOMString NDEFRecordType;
typedef (DOMString or ArrayBuffer or NDEFMessageInit) NDEFMessageSource;
[SecureContext, Exposed=Window]
interface NFCWriter {
  constructor();
  Promise<void> push(NDEFMessageSource message, optional NFCPushOptions options={});
};
[SecureContext, Exposed=Window]
interface NFCReader : EventTarget {
  constructor();
  attribute EventHandler onreading;
  attribute EventHandler onerror;
  void scan(optional NFCScanOptions options={});
};
[SecureContext, Exposed=Window]
interface NFCReadingEvent : Event {
  constructor(DOMString type, NFCReadingEventInit readingEventInitDict);
  readonly attribute DOMString serialNumber;
  [SameObject] readonly attribute NDEFMessage message;
};
dictionary NFCReadingEventInit : EventInit {
  DOMString? serialNumber = "";
  required NDEFMessageInit message;
};
[SecureContext, Exposed=Window]
interface NFCErrorEvent : Event {
  constructor(DOMString type, NFCErrorEventInit errorEventInitDict);
  readonly attribute DOMException error;
};
dictionary NFCErrorEventInit : EventInit {
  required DOMException error;
};
dictionary NFCPushOptions {
  NFCPushTarget target = "any";
  unrestricted double timeout = Infinity;
  boolean ignoreRead = true;
  AbortSignal? signal;
};
enum NFCPushTarget {
  "tag",
  "peer",
  "any"
};
  

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

B. 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, Wanming Lin, and François Beaufort 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.

C. References

C.1 Normative references

[dom]
DOM Standard . Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification . Ecma International. URL: https://tc39.github.io/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-RTD]
NFC Record Type Definition (RTD) 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/
[PERMISSIONS]
Permissions . Mounir Lamouri; Marcos Caceres; Jeffrey Yasskin. W3C. 25 September 2017. W3C Working Draft. URL: https://www.w3.org/TR/permissions/ [promises-guide] Writing Promise-Using Specifications . Domenic Denicola. W3C. 9 November 2018. TAG Finding. URL: https://www.w3.org/2001/tag/doc/promises-guide
[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
[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/

C.2 Informative references

[secure-contexts]
Secure Contexts . Mike West. W3C. 15 September 2016. W3C Candidate Recommendation. URL: https://www.w3.org/TR/secure-contexts/