Copyright © 2019 the Contributors to the Web NFC API Specification, published by the Web NFC Community Group under the W3C Community Contributor License Agreement (CLA). A human-readable summary is available.
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.
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.
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.
The Augmented Backus-Naur Form (ABNF) notation used is specified in [RFC5234].
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.
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. 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 records.
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.
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.
The NFC Record Type Definition (RTD) Technical Specification requires that the TYPE field names MUST be compared in case-insensitive manner.
The NFC Forum has standardized a small set of useful RTD (Record Type Definition) types for use in the NFC Forum well-known type 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 (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.
The MIME type records are records that store opaque
data with associated MIME type.
Web NFC has special handling for working with JSON MIME type data.
In absolute-URL records the TYPE field contains the absolute-URL string, and not the payload.
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.
The NFC Forum external type records are for client specified data and must have a type name following the NFC Record Type Definition (RTD) Technical Specification standard.
Web NFC defines a special external type record that is not accessible to client applications.
The unknown records are records that store
opaque
data without associated MIME type.
The unchanged records 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.
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 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 five different tag types to be operable with NFC devices. The same is required on operating systems such as Android.
96
bytes and
2
Kbytes. Communication speed is 106
kbit/sec.
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.
1
MByte per service.
Communication speed is 106
kbit/sec. Like Type 2, it supports
anti-collision protection.
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 such as 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 function.
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.
This section is non-normative.
This section shows how developers can make use of the various features of this specification.
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.
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.
Document
of the top-level browsing context using the
Web NFC API is visible and focused.
Document
using the Web NFC API is
visible or focused.
This use case is not supported in this version of the specification, and it has low priority for future versions as well.
The user opens a web page which can write an NFC tag. The write operations may be one of the following:
Note that an NFC write operation to an NFC tag always involves also a read operation.
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
,
then the content is delivered to the page through the NFCReader
NFCReadingEvent
.
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 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.
This use case is not supported in this version of the specification.
Users may attach one or more external NFC adapters to their devices, in addition to a built-in adapter. Users may use either NFC adapter.
This section is non-normative.
High level features for the Web NFC specification include the following:
This specification makes a few simplifications in what use cases and data types the Web NFC API can handle:
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.
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 author, unless a prearranged trust relationship exists.
The main threats are summarized in the Security and Privacy document.
In this specification the following threats are handled with the highest priority:
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.
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 permissions that are preserved beyond the current browsing session MUST be revocable.
This section is non-normative.
This section summarizes the security policies which are specified as normative requirements in the respective algorithms of this specification.
Only secure contexts are allowed to access NFC content. Browsers may ignore this rule for development purposes only.
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:
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.
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.10 Writing or pushing content section.
Pushing Web NFC content to an NFC tag does not need to obtain permission, if the message author host of the author type record on that NFC tag is equal to the serialized host 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.10 Writing or pushing content section.
Since all local content that a web page has access to can be shared with NFC, the user needs to be clearly aware about the permissions granted to the web page using the Web NFC API.
When pushing Web NFC content, the serialized host and the URL path of the current settings object when requesting the operation must be recorded in each sent NDEF message's author type record. For details see the § 9.10 Writing or pushing content section.
When listening for and pushing NFC content, the UA may warn the user that the given origin may be able to infer physical location.
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.
NDEFMessage
interface
The content of any Web NFC message is exposed by the
NDEFMessage
interface:
[Constructor(NDEFMessageInit
messageInit), Exposed=Window] interfaceNDEFMessage
{ readonly attribute USVStringurl
; readonly attribute FrozenArray<NDEFRecord
>records
; }; dictionaryNDEFMessageInit
{ USVStringurl
; sequence<NDEFRecordInit
>records
; };
The url
property represents the message author of a received
Web NFC message.
The records
property represents a list of NDEF records 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 author of the pushed Web NFC content.
NDEFRecord
interface
The content of any NDEF record is exposed by the
NDEFRecord
interface:
typedef anyNDEFRecordData
; [Constructor(NDEFRecordInit
recordInit), Exposed=Window] interfaceNDEFRecord
{ readonly attributeNDEFRecordType
recordType
; readonly attribute USVStringmediaType
; USVString?toText
(); [NewObject] ArrayBuffer?toArrayBuffer
(); [NewObject] object?toJSON
(); }; dictionaryNDEFRecordInit
{NDEFRecordType
recordType
; USVStringmediaType
;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 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 NDEFRecordInit
dictionary is used to initialize an NDEF record
with its type, MIME type and payload data via the members of
recordType
, mediaType
,
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.12 Receiving and parsing content and § 9.10 Writing or pushing content sections.
To convert NDEFRecord.[[PayloadData]] bytes, pass a record and a type, run these steps:
recordType
attribute.
empty
", return null
.
text
", then run the following sub-steps:
utf-8
" if bit 7
(MB field) of
header is equal to the value 0, or else "utf-16be
".
5
to bit 0
of the
header.
1
to the end.
utf-8
", return the result of
running UTF-8 decode on buffer.
encoding
set to "utf-16be
".
json
" or
"opaque
", then return an ArrayBuffer
whose contents are the
bytes. Re-throw any exceptions.
null
.
json
" or
"opaque
", then return the result of running parse JSON from bytes
on bytes. Re-throw any exceptions.
null
.
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 types.
NDEFRecord
.
NDEFRecord
of a text type.
NDEFRecord
of a url type.
NDEFRecord
of a smart-poster type.
NDEFRecord
of a json type.
NDEFRecord
of an opaque type.
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
".
And additional ABNF exists for well-known type records:
wkt-type = (ALPHA / DIGIT) *(ALPHA / DIGIT / other)
The NFC Record Type Definition (RTD) Technical Specification defines every type in the well-known type records and external type records in terms of URNs, but only a subset of the URN is actually stored in the NDEF record's TYPE field, which corresponds to the above two ABNFs.
The mapping from data types of an NDEFRecordInit
to
NDEF record types, as used in the § 9.10 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 orany typed array type |
External type record |
The mapping from NDEF record types to NDEFRecord
,
as used for incoming NDEF messages described in the
§ 9.12 Receiving and parsing content section, is as
follows:
NDEF record type | NDEFRecord recordType | NDEFRecord mediaType | NDEFRecord data getters |
---|---|---|---|
Empty record | "empty " |
empty |
toText() ortoJSON() ortoArrayBuffer()
|
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 " |
"" |
toRecord() ortoArrayBuffer()
|
Absolute-URL record | "url " |
"text/plain " |
toText() |
MIME type record with JSON MIME type | "json " |
The MIME type used in the NDEF record |
toText() ortoJSON() ortoArrayBuffer()
|
MIME type record | "opaque " |
The MIME type used in the NDEF record |
toText() ortoJSON() ortoArrayBuffer()
|
External type record with type other than
w3.org:A |
external type | "application/octet-stream " |
toText() ortoJSON() ortoArrayBuffer()
|
Any other NDEF record type | "opaque " |
"application/octet-stream " |
toText() ortoJSON() ortoArrayBuffer()
|
The author type records MUST NOT be exposed to client browsing contexts.
typedef (DOMString or ArrayBuffer orNDEFMessageInit
)NDEFMessageSource
; [Constructor, SecureContext, Exposed=Window] interfaceNFCWriter
{ Promise<void>push
(NDEFMessageSource
message, optionalNFCPushOptions
options={}); }; [Constructor, SecureContext, Exposed=Window] interfaceNFCReader
: EventTarget { attribute EventHandleronreading
; attribute EventHandleronerror
; voidscan
(optionalNFCScanOptions
options={}); }; [Constructor(DOMString type,NFCReadingEventInit
readingEventInitDict), SecureContext, Exposed=Window] interfaceNFCReadingEvent
: Event { readonly attribute DOMStringserialNumber
; [SameObject] readonly attributeNDEFMessage
message
; }; dictionaryNFCReadingEventInit
: EventInit { DOMString?serialNumber
= ""; requiredNDEFMessageInit
message
; }; [Constructor(DOMString type,NFCErrorEventInit
errorEventInitDict), SecureContext, Exposed=Window] interfaceNFCErrorEvent
: Event { readonly attribute DOMExceptionerror
; }; dictionaryNFCErrorEventInit
: EventInit { required DOMExceptionerror
; };
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.
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.
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.
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 instances initially set to the empty set.
|
[[PendingPush]] |
A promise-writer tuple where the promise holds a pending Promise and
writer holds a . 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
.
Internal slots are used only as a notation in this specification, and implementations do not necessarily have to map them to explicit internal properties.
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
while suspended.
However, platform level timers for the
NFCReader
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.
To attempt to abort a pending push operation on an environment settings object, perform the following steps:
"AbortError"
DOMException
and abort these steps.
Rejecting p will clear the pending push tuple and remove the async write handlers as it is a transformed promise with fulfillment and rejection handlers.
To release NFC on an environment settings object, perform the following steps:
The UA must release NFC given the document's relevant settings object as additional unloading document cleanup steps.
NDEFCompatibility
enumTo describe what NDEF compatible devices are accepted as vendor specific tags exist that support NDEF but which are not universally supported by all NFC readers, or by the NFC standard.
enum NDEFCompatibility
{
"nfc-forum
",
"vendor
",
"any
"
};
nfc-forum
vendor
any
NFCPushOptions
dictionarydictionary NFCPushOptions
{
NFCPushTarget
target
= "any";
unrestricted double timeout
= Infinity;
boolean ignoreRead
= true;
AbortSignal? signal
;
NDEFCompatibility
compatibility
= "nfc-forum";
};
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.
The compatibility
property denotes
the accepted kind of NFC devices.
NFCPushTarget
enumThis enum defines the set of intended target values for the push() operation.
enum NFCPushTarget
{
"tag
",
"peer
",
"any
"
};
tag
peer
any
NFCScanOptions
dictionary
To describe which messages an application is interested in, the
NFCScanOptions
dictionary is used:
dictionary NFCScanOptions
{
AbortSignal? signal
;
USVString url
= "";
NDEFRecordType
recordType
;
USVString mediaType
= "";
NDEFCompatibility
compatibility
= "nfc-forum";
};
The signal
property allows to abort the
scan() operation.
The url
property
denotes the URL pattern which is used for matching the
message author of Web NFC messages 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.
The compatibility
property denotes
the accepted kind of NFC devices.
const options = {
url: "https://www.w3.org/*", // any path from the domain is accepted
recordType: "json",
mediaType: "application/*+json" // any JSON-based MIME type
}
const options = {
url: "https://w3.org/info/restaurant/daily-menu/",
recordType: "opaque",
mediaType: "application/octet-stream"
}
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 messages that can be set for pushing for an origin: one targeted to NFC tags and one to NFC peers, until the current message is sent, a timeout happens, or the push is aborted.
The
NFCWriter.push
method, when invoked, MUST run the
push a message algorithm:
Promise
object.
null
otherwise.
"NotSupportedError"
DOMException
and return p.
"NotReadableError"
DOMException
and return p.
"NotSupportedError"
DOMException
and return p.
"AbortError"
DOMException
and return p.
null
, then
add the following abort steps to signal:
"AbortError"
DOMException
and abort these steps.
"NotSupportedError"
DOMException
and abort these steps.
NDEFMessageSource
union, reject p
with a TypeError
, and abort these steps.
NDEFMessageInit
type, and message's records
is empty, reject p with
a TypeError
and abort these steps.
NaN
or negative, reject
p with a TypeError
and abort
these steps.
"NotSupportedError"
DOMException
and abort these steps.
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.
Infinity
,
start a timer timer with the timeout value set to
timeout.
"TimeoutError"
DOMException
.
vendor
" or "any
".
tag
" or "any
".
peer
" or
"any
".
true
, run the
receiving steps.
null
, or different than the
serialized host of the
current settings object's origin, and the
obtain push permission steps return
false
, then reject p with
"NotAllowedError"
DOMException
and abort these steps.
"NetworkError"
DOMException
and abort these steps.
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 adapters. 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 adapters.
this
, transformedPromise).
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.
To obtain push permission, run these steps:
true
.
"granted"
(i.e. an expressed permission has been granted
to the origin and global object using
the Permissions API), return true
.
"prompt"
, then optionally
request permission
from the user for the Web NFC permission name.
If that is granted, return true
.
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
.
false
.
To create Web NFC message given a message run these steps:
undefined
:
undefined
, reject promise
a TypeError
and abort these steps.
DOMString
, then set record's recordType to "text
".
ArrayBuffer
, then set record's recordType
to "opaque
".
json
".
empty
"text
"url
"json
"opaque
"Implementations may choose the location of the author type record within the NDEF message.
To map empty record to NDEF given a record, run these steps:
0
(empty record).
0
.
0
,
and omit TYPE field and PAYLOAD field.
To map text to NDEF given a record, run these steps:
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
".
DOMString
,
throw a TypeError
and abort these steps.
text
", and subtype is "plain
".
text
", then throw a
"SyntaxError"
DOMException
and abort these steps.
lang
"] if it
exists, or "en
".
charset
"] if it
exists, or "utf-8
".
utf-8
",
throw a TypeError
.
7
to the value 0
(meaning UTF-8 encoding).
6
to the value 0
(reserved).
SyntaxError
.
5
to bit 0
to languageLength.
1
(well-known type record).
T
" (0x54
).
0
, set the ndefRecord's PAYLOAD field to data.
The lang=
parameter is a non-standard parameter
to MIME types, but it is used in this specification
in order to maintain compatibility with NFC Forum Technical Specifications.
To map a URL to NDEF given a record, run these steps:
DOMString
,
throw a TypeError
and abort these steps.
TypeError
and abort these steps.
0
.
1
(well-known type record).
U
" (0x55
).
0
, set the ndefRecord's PAYLOAD field to data.
To map JSON to NDEF given a record, run these steps:
TypeError
and abort these steps.
application
", and subtype is "json
".
"SyntaxError"
DOMException
and abort these steps.
2
(MIME type).
0
, set the ndefRecord's PAYLOAD field to data.
To map binary data to NDEF given a record, run these steps:
ArrayBuffer
, throw a TypeError
and abort these steps.
application
", and subtype is "octet-stream
".
2
(MIME type).
0
, set the ndefRecord's PAYLOAD field to data.
To listen for NFC content, the client MUST activate an
instance by calling NFCReader
NFCReader.scan()
. When attaching
an event listener for the "reading
" event on it, NFC content is
accessible to the client.
Each
can filter the NFC content based on
data type, and the URL path of the
browsing context which has been saved to the author type record
of the NFC content.
NFCReader
If you filter by URL path, that means it will be matched against the author type record, 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 patterns associated with the activated reader objects.
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 types,
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.
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 author |
---|---|
host |
exact match or ends with (URL pattern's
host prepended
with ". ").
|
path |
If URL pattern's path is "/* ", match any
message author path. Otherwise, begins with URL pattern's
path.
|
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.
true
.
false
.
false
.
.
"
to pattern's host.
false
.
/*
", return true
.
true
.
false
.
The section § 9.12 Receiving and parsing content uses
instances to match
incoming NFC content.
NFCReader
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:
NFCReader
instance.
signal
", set
reader.[[Signal]] to value.
url
", set
reader.[[Url]] to value, prepended with "https://
".
recordType
", set
reader.[[RecordType]] to value.
mediaType
", set
reader.[[MediaType]] to value.
compatibility
", set
reader.[[Compatibility]] to value.
"NotSupportedError"
DOMException
.
error
" at reader
using NFCErrorEvent
with its error attribute
initialized to e.
"NotReadableError"
DOMException
.
error
" at reader
using NFCErrorEvent
with its error attribute
initialized to e.
null
, then
add the following abort steps to reader.[[Signal]]:
NFCReader
instance from the activated reader objects.
false
, then
"NotAllowedError"
DOMException
.
error
" at reader
using NFCErrorEvent
with its error attribute
initialized to e.
"NotSupportedError"
DOMException
.
error
" at reader
using NFCErrorEvent
with its error attribute
initialized to e.
"SyntaxError"
DOMException
.
error
" at reader
using NFCErrorEvent
with its error attribute
initialized to e.
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:
true
.
scan()
as well, then return false
.
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.
In this step UAs are advised to notify users about that reading NFC content may indirectly reveal the physical location of the user.
true
.
If there are any
instances in activated reader objects
then UAs MUST listen to NDEF messages, according to step 3
of the NFC listen algorithm.
NFCReader
T
recordsTo parse a NDEF text record given a ndefRecord into a record, run these steps:
5
to bit 0
of the header.
1
byte, inclusive.
text
", subtype "plain
" and parameters
equal to an empty ordered map.
lang
"] to language.
text
".
Using the encoder, it is only possible
to encode as UTF-8, unless you do the encoding manually
and use the "opaque
"
, which
allows you to write any opaque data.
recordType
When you write a string to the "text
"
, 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 recordType
which will always return the data
as a string.
NFCReader
As external applications may have encoded the "opaque
"
using a different
encoding, which can be decoded using Encoding Standard if you know
the encoding.
recordType
U
recordsTo parse a NDEF URL record given a ndefRecord into a record, run these steps:
url
".
text/plain
".
0
, then match the prefixByte against
the prefix codes in NFC Forum Technical Specifications,
URI Record Type Definition specification, Section 3.2.2.
Sp
recordsTo parse a NDEF smart-poster record given a ndefRecord into a record, run these steps:
smart-poster
".
To parse a NDEF MIME type record given a ndefRecord into a record, run these steps:
json
".
opaque
".
To parse a NDEF absolute-URL record given a ndefRecord into a record, run these steps:
url
".
text/plain
".
To parse a NDEF external type record given a ndefRecord into a record, run these steps:
application/octet-stream
".
To parse a NDEF unknown record given a ndefRecord into a record, run these steps:
opaque
".
The UA SHOULD represent an unformatted NFC tag as an NDEF message containing a single empty NDEF record.
vendor
" if the read NDEF
compatible device is not officially supported by the NFC Forum, or else
"nfc-forum
".
NDEFMessage
object, with
message's url set to null
and
message's records set to the empty list.
null
if unavailable.
null
, set it to the
string of U+003A (:
) concatenating each number represented as
ASCII hex digit, in the same order.
NDEFRecord
object.
0
(empty record), then set
record's recordType to "empty
" and set record's mediaType to ""
.
1
(well-known type record):
T
" (0x54
)U
" (0x55
)Sp
" (0x53
0x70
)2
(MIME type record), then
set record to the result of running parse a NDEF MIME type record
on ndef, or make sure that the underlying platform provides equivalent
values to the record object's properties.
3
(absolute-URL record), then
set record to the result of running parse a NDEF absolute-URL record
on ndef.
4
and
ndef's lowercased TYPE field is "w3.org:a
" (author type record),
then set message's url to the ndef's PAYLOAD field.
4
(external type record),
then set record to the result of running parse a NDEF external type record
on ndef, or make sure that the underlying platform provides equivalent values
to the record object's properties.
5
(unknown record)
then set record to the result of running parse a NDEF unknown record
on ndef, or make sure that the underlying platform provides equivalent values
to the record object's properties.
To dispatch NFC content given a serialNumber
of type serialNumber
, message
of type NDEFMessage
and compatibility of type
NDEFCompatibility
, run these steps:
NFCReader
instance reader in
the activated reader objects, run the following sub-steps:
false
, continue.
""
and
it is not equal to any record's mediaType where record is
an element of message, continue.
any
", and
not equal to compatibility, continue.
reading
" at reader
using NFCReadingEvent
with its serialNumber
attribute
initialized to serialNumber and message
attribute
initialized to message.
[Constructor(NDEFMessageInit
messageInit), Exposed=Window] interfaceNDEFMessage
{ readonly attribute USVStringurl
; readonly attribute FrozenArray<NDEFRecord
>records
; }; dictionaryNDEFMessageInit
{ USVStringurl
; sequence<NDEFRecordInit
>records
; }; typedef anyNDEFRecordData
; [Constructor(NDEFRecordInit
recordInit), Exposed=Window] interfaceNDEFRecord
{ readonly attributeNDEFRecordType
recordType
; readonly attribute USVStringmediaType
; USVString?toText
(); [NewObject] ArrayBuffer?toArrayBuffer
(); [NewObject] object?toJSON
(); }; dictionaryNDEFRecordInit
{NDEFRecordType
recordType
; USVStringmediaType
;NDEFRecordData
data
; }; typedef DOMStringNDEFRecordType
; typedef (DOMString or ArrayBuffer orNDEFMessageInit
)NDEFMessageSource
; [Constructor, SecureContext, Exposed=Window] interfaceNFCWriter
{ Promise<void>push
(NDEFMessageSource
message, optionalNFCPushOptions
options={}); }; [Constructor, SecureContext, Exposed=Window] interfaceNFCReader
: EventTarget { attribute EventHandleronreading
; attribute EventHandleronerror
; voidscan
(optionalNFCScanOptions
options={}); }; [Constructor(DOMString type,NFCReadingEventInit
readingEventInitDict), SecureContext, Exposed=Window] interfaceNFCReadingEvent
: Event { readonly attribute DOMStringserialNumber
; [SameObject] readonly attributeNDEFMessage
message
; }; dictionaryNFCReadingEventInit
: EventInit { DOMString?serialNumber
= ""; requiredNDEFMessageInit
message
; }; [Constructor(DOMString type,NFCErrorEventInit
errorEventInitDict), SecureContext, Exposed=Window] interfaceNFCErrorEvent
: Event { readonly attribute DOMExceptionerror
; }; dictionaryNFCErrorEventInit
: EventInit { required DOMExceptionerror
; }; enumNDEFCompatibility
{ "nfc-forum
", "vendor
", "any
" }; dictionaryNFCPushOptions
{NFCPushTarget
target
= "any"; unrestricted doubletimeout
= Infinity; booleanignoreRead
= true; AbortSignal?signal
;NDEFCompatibility
compatibility
= "nfc-forum"; }; enumNFCPushTarget
{ "tag
", "peer
", "any
" }; dictionaryNFCScanOptions
{ AbortSignal?signal
; USVStringurl
= "";NDEFRecordType
recordType
; USVStringmediaType
= "";NDEFCompatibility
compatibility
= "nfc-forum"; };
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.