Skip to main content
An in-page NFC scan, available on Android Chrome in a secure context. It reads a tap with the device’s own NDEF reader and shapes it like every other tap source, so a core client dispatches to it through captureTap(). defaultTapSources() already includes it; register it directly only when you build the source list yourself. This is a progressive enhancement, not a replacement for the redirect source. iOS has no in-page scanning, and some Android NFC stacks detect a tag but return an empty read, so treat any failure as a cue to fall back to opening the tap link. A scan needs a live user gesture to raise the permission prompt, so run the capture from a control the user pressed, never at page load.

Example

Parameters

WebNfcTapSourceOptions
Optional configuration.
() => WebNfcWindow | undefined
Test seam that supplies the window the source reads NDEFReader and the permissions API from. Defaults to the page’s own window. Leave it unset in product code.

Returns

A TapSource named web-nfc that a core client registers and dispatches to.
string
required
The source identifier, web-nfc. Pass it to captureTap({ only: [...] }) to target this source, and match it against a captured tap’s source.
number
required
WEB_NFC_TAP_SOURCE_PRIORITY, which is 0.
() => boolean
required
True when the device exposes NDEFReader. Synchronous on purpose, so capture() runs in the same task and the gesture that gates the permission prompt stays live.
(options?) => Promise<TapResult | null>
required
Starts a scan and resolves with the captured tap. Resolves null for a readable tag that is not an Endstate chip, or when no reader is present. Rejects with a WebNfcError when a scan fails in a way the interface should present distinctly.

Priority

WEB_NFC_TAP_SOURCE_PRIORITY is 0, below the redirect source’s 20. A tap already in the URL wins: on a page opened by a tap, the redirect source resolves from the URL before any scan starts. The scanner only runs when no higher-priority source captures.
Web NFC requires Android Chrome on a secure context (HTTPS or localhost). isAvailable() returns false everywhere else, and dispatch moves on to the next source.

See also