
Product
Introducing Repository Access Permissions and Custom Roles
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.
@capgo/capacitor-nfc
Advanced tools
Native NFC tag discovery, reading and writing for Capacitor apps on iOS and Android.
Native NFC tag detection, reading, and writing for Capacitor apps on iOS and Android.
Modern Capacitor port of the battle-tested phonegap-nfc plugin, aligned with Capgo conventions and tooling.
The most complete documentation will live on the Capgo docs portal. Until then, explore the TypeScript definitions (src/definitions.ts) and run the included example app for a tour of the API.
| Plugin version | Capacitor compatibility | Maintained |
|---|---|---|
| v8.*.* | v8.*.* | ✅ |
| v7.*.* | v7.*.* | On demand |
| v6.*.* | v6.*.* | ❌ |
| v5.*.* | v5.*.* | ❌ |
Note: The major version of this plugin follows the major version of Capacitor. Use the version that matches your Capacitor installation (e.g., plugin v8 for Capacitor 8). Only the latest major version is actively maintained.
You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command:
npx skills add https://github.com/cap-go/capacitor-skills --skill capacitor-plugins
Then use the following prompt:
Use the `capacitor-plugins` skill from `cap-go/capacitor-skills` to install the `@capgo/capacitor-nfc` plugin in my project.
If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:
npm install @capgo/capacitor-nfc
npx cap sync
Remember to add the required platform configuration:
AndroidManifest.xml declares the android.permission.NFC permission.NFCReaderUsageDescription to your app Info.plist to explain why NFC access is needed.iosSessionType: 'tag'): to use the tag session type you must also add the Near Field Communication Tag Reader Session Formats entitlement (com.apple.developer.nfc.readersession.formats) to your app's entitlements file and include the TAG format (and optionally NDEF). Without this entitlement the session will fail to start.Before attempting to use NFC features, you can check if the device has NFC hardware:
import { CapacitorNfc } from '@capgo/capacitor-nfc';
const { supported } = await CapacitorNfc.isSupported();
if (!supported) {
console.warn('This device does not have NFC hardware');
// Hide NFC features in your UI
} else {
// Check if NFC is currently enabled
const { status } = await CapacitorNfc.getStatus();
if (status === 'NFC_DISABLED') {
console.warn('NFC is disabled. Prompt user to enable it.');
// Optionally show settings button
}
}
import { CapacitorNfc } from '@capgo/capacitor-nfc';
await CapacitorNfc.startScanning({
invalidateAfterFirstRead: false, // keep the session open so we can write later
alertMessage: 'Hold a tag near the top of your device.',
});
const listener = await CapacitorNfc.addListener('nfcEvent', (event) => {
console.info('Tag type:', event.type);
console.info('First record:', event.tag?.ndefMessage?.[0]);
});
// Later, write a simple text record back to the tag
const encoder = new TextEncoder();
const langBytes = Array.from(encoder.encode('en'));
const textBytes = Array.from(encoder.encode('Hello Capgo'));
const payload = [langBytes.length & 0x3f, ...langBytes, ...textBytes];
await CapacitorNfc.write({
allowFormat: true,
records: [
{
tnf: 0x01,
type: [0x54], // 'T'
id: [],
payload,
},
],
});
await listener.remove();
await CapacitorNfc.stopScanning();
import { CapacitorNfc } from '@capgo/capacitor-nfc';
// Use 'tag' session type to read raw (non-NDEF) tags
await CapacitorNfc.startScanning({
iosSessionType: 'tag', // Enable raw tag reading on iOS
alertMessage: 'Hold your card near the device',
});
const listener = await CapacitorNfc.addListener('nfcEvent', (event) => {
console.info('Tag detected:', event.type); // 'tag' or 'ndef'
// Read the UID (identifier) - works for both NDEF and raw tags
if (event.tag?.id) {
const uid = event.tag.id.map(byte => byte.toString(16).padStart(2, '0').toUpperCase()).join(':');
console.info('Tag UID:', uid); // e.g., "04:A1:B2:C3:D4:E5:F6"
}
// If the tag has NDEF data, it will also be available
if (event.tag?.ndefMessage) {
console.info('NDEF records:', event.tag.ndefMessage);
}
});
await listener.remove();
await CapacitorNfc.stopScanning();
startScanning(...)stopScanning()write(...)erase()makeReadOnly()share(...)unshare()getStatus()showSettings()getPluginVersion()isSupported()addListener('nfcEvent', ...)addListener('tagDiscovered' | 'ndefDiscovered' | 'ndefMimeDiscovered' | 'ndefFormatableDiscovered', ...)addListener('nfcStateChange', ...)Public API surface for the Capacitor NFC plugin.
The interface intentionally mirrors the behaviour of the reference PhoneGap implementation to ease migration while embracing idiomatic Capacitor APIs.
startScanning(options?: StartScanningOptions | undefined) => Promise<void>
Starts listening for NFC tags.
| Param | Type |
|---|---|
options | StartScanningOptions |
stopScanning() => Promise<void>
Stops the ongoing NFC scanning session.
write(options: WriteTagOptions) => Promise<void>
Writes the provided NDEF records to the last discovered tag.
| Param | Type |
|---|---|
options | WriteTagOptions |
erase() => Promise<void>
Attempts to erase the last discovered tag by writing an empty NDEF message.
makeReadOnly() => Promise<void>
Attempts to make the last discovered tag read-only.
share(options: ShareTagOptions) => Promise<void>
Shares an NDEF message with another device via peer-to-peer (Android only).
| Param | Type |
|---|---|
options | ShareTagOptions |
unshare() => Promise<void>
Stops sharing previously provided NDEF message (Android only).
getStatus() => Promise<{ status: NfcStatus; }>
Returns the current NFC adapter status.
Returns: Promise<{ status: NfcStatus; }>
showSettings() => Promise<void>
Opens the system settings page where the user can enable NFC.
getPluginVersion() => Promise<{ version: string; }>
Returns the version string baked into the native plugin.
Returns: Promise<{ version: string; }>
isSupported() => Promise<{ supported: boolean; }>
Checks whether the device has NFC hardware support.
Returns true if NFC hardware is present on the device, regardless of
whether NFC is currently enabled or disabled. Returns false if the
device does not have NFC hardware.
Use this method to determine if NFC features should be shown in your
app's UI. To check if NFC is currently enabled, use getStatus().
Returns: Promise<{ supported: boolean; }>
addListener(eventName: 'nfcEvent', listenerFunc: (event: NfcEvent) => void) => Promise<PluginListenerHandle>
| Param | Type |
|---|---|
eventName | 'nfcEvent' |
listenerFunc | (event: NfcEvent) => void |
Returns: Promise<PluginListenerHandle>
addListener(eventName: 'tagDiscovered' | 'ndefDiscovered' | 'ndefMimeDiscovered' | 'ndefFormatableDiscovered', listenerFunc: (event: NfcEvent) => void) => Promise<PluginListenerHandle>
| Param | Type |
|---|---|
eventName | 'tagDiscovered' | 'ndefDiscovered' | 'ndefMimeDiscovered' | 'ndefFormatableDiscovered' |
listenerFunc | (event: NfcEvent) => void |
Returns: Promise<PluginListenerHandle>
addListener(eventName: 'nfcStateChange', listenerFunc: (event: NfcStateChangeEvent) => void) => Promise<PluginListenerHandle>
| Param | Type |
|---|---|
eventName | 'nfcStateChange' |
listenerFunc | (event: NfcStateChangeEvent) => void |
Returns: Promise<PluginListenerHandle>
Options controlling the behaviour of {@link CapacitorNfcPlugin.startScanning}.
| Prop | Type | Description |
|---|---|---|
invalidateAfterFirstRead | boolean | iOS-only: closes the NFC session automatically after the first successful tag read. Defaults to true. |
alertMessage | string | iOS-only: custom message displayed in the NFC system sheet while scanning. |
iosSessionType | 'tag' | 'ndef' | iOS-only: session type to use for NFC scanning. - 'ndef': Uses NFCNDEFReaderSession (default). Only detects NDEF-formatted tags. - 'tag': Uses NFCTagReaderSession. Detects both NDEF and non-NDEF tags (e.g., raw MIFARE tags). Allows reading UID from unformatted tags. Requires the Near Field Communication Tag Reader Session Formats entitlement in your app with the TAG format included. Without it the session will fail to start and the promise will reject with a NO_NFC error code. Defaults to 'ndef' for backward compatibility. |
iosPollingOptions | NfcIosPollingOption[] | iOS-only: polling options to use for NFC scanning. Defaults to ['iso14443', 'iso15693', 'iso18092'] for backward compatibility. |
androidReaderModeFlags | number | Android-only: raw flags passed to NfcAdapter.enableReaderMode. Defaults to enabling all tag types with skipping NDEF checks. |
Options used when writing an NDEF message on the current tag.
| Prop | Type | Description |
|---|---|---|
records | NdefRecord[] | Array of records that compose the NDEF message to be written. |
allowFormat | boolean | When true, the plugin attempts to format NDEF-formattable tags before writing. Defaults to true. |
JSON structure representing a single NDEF record.
Mirrors the data format returned by the legacy Cordova implementation and uses integer arrays instead of strings to preserve the original payload bytes.
| Prop | Type | Description |
|---|---|---|
tnf | number | Type Name Format identifier. |
type | number[] | Type field expressed as an array of byte values. |
id | number[] | Record identifier expressed as an array of byte values. |
payload | number[] | Raw payload expressed as an array of byte values. |
Options used when sharing an NDEF message with another device using Android Beam / P2P mode.
| Prop | Type |
|---|---|
records | NdefRecord[] |
| Prop | Type |
|---|---|
remove | () => Promise<void> |
Generic NFC discovery event dispatched by the plugin.
| Prop | Type |
|---|---|
type | NfcEventType |
tag | NfcTag |
Representation of the full tag information returned by the native layers.
Supports standard NFC Forum tags as well as MIFARE Ultralight cards (including EV1 and NTAG variants). NDEF data is automatically extracted from MIFARE Ultralight tags when available.
| Prop | Type | Description |
|---|---|---|
id | number[] | Raw identifier bytes for the tag. |
techTypes | string[] | List of Android tech strings (e.g. android.nfc.tech.Ndef). |
type | string | null | Human readable tag type when available (e.g. NFC Forum Type 2, MIFARE Ultralight). |
maxSize | number | null | Maximum writable size in bytes for tags that expose NDEF information. |
isWritable | boolean | null | Indicates whether the tag can be written to. |
canMakeReadOnly | boolean | null | Indicates whether the tag can be permanently locked. |
ndefMessage | NdefRecord[] | null | Array of NDEF records discovered on the tag. |
Event emitted whenever the NFC adapter availability changes.
| Prop | Type |
|---|---|
status | NfcStatus |
enabled | boolean |
iOS-specific polling options for NFC scanning sessions. These options determine the type of tags that a reader session should detect during a polling sequence.
'iso14443' | 'iso15693' | 'iso18092' | 'pace'
Possible NFC adapter states returned by {@link CapacitorNfcPlugin.getStatus}.
Matches the constants provided by the original PhoneGap NFC plugin for compatibility with existing applications.
'NFC_OK' | 'NO_NFC' | 'NFC_DISABLED' | 'NDEF_PUSH_DISABLED'
Event type describing the kind of NFC discovery that happened.
tag: A generic NFC tag (no NDEF payload).ndef: A tag exposing an NDEF payload.ndef-mime: An NDEF tag that matched one of the MIME type filters.ndef-formatable: A tag that can be formatted to NDEF.'tag' | 'ndef' | 'ndef-mime' | 'ndef-formatable'
FAQs
Native NFC tag discovery, reading and writing for Capacitor apps on iOS and Android.
We found that @capgo/capacitor-nfc demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.