Cross-platform NFC library for Node.js Read and write NFC tags and smart cards using built-in PC/SC bindings. Works on Linux, macOS, and Windows.
- Overview
- Installation
- NFC Tag Handling Flow
- Basic Usage
- Alternative Usage (Manual Processing)
- Reading & Writing Data
- FAQ
- Common Issues
- Disclaimer
- License
nfc-pcsclite provides a low-level Node.js interface for NFC operations using PC/SC bindings.
It supports automatic card detection, UID reading, and communication with Android HCE devices.
✅ Supports card UID auto-reading
✅ Works with ACR122 USB reader and other PC/SC-compliant devices
✅ Includes native pcsclite bindings
⚠️ If card detection fails, check the Alternative Usage section.
Compatible with Node.js 18 or newer.
This package includes native bindings built with node-gyp. Ensure you have a C/C++ toolchain installed for your OS. See node-gyp Installation Guide.
-
macOS / Windows: Already included.
-
Linux / UNIX: Install manually:
apt-get install libpcsclite1 libpcsclite-dev pcscd# Using npm
npm install nfc-pcsclite
# Using Yarn
yarn add nfc-pcscliteWhen a tag is detected, the following occurs:
- Detects the card standard (
TAG_ISO_14443_3orTAG_ISO_14443_4); - Connects to the card;
- Depending on
autoProcessing:true(default): automatically retrieves UID or APDU data; orfalse: triggerscardevent only, letting you handle transmission manually;
- You can then read, write, or send custom commands.
import { NFC } from 'nfc-pcsc';
const nfc = new NFC(); // optional: pass a logger (e.g. Pino, Winston)
nfc.on('reader', reader => {
console.log(`${reader.reader.name} device attached`);
reader.on('card', card => {
console.log(`${reader.reader.name} card detected`, card);
});
reader.on('card.off', card => {
console.log(`${reader.reader.name} card removed`, card);
});
reader.on('error', err => {
console.error(`${reader.reader.name} error`, err);
});
reader.on('end', () => {
console.log(`${reader.reader.name} device removed`);
});
});
nfc.on('error', err => {
console.error('An error occurred', err);
});import { NFC } from 'nfc-pcsc';
const nfc = new NFC();
nfc.on('reader', reader => {
reader.autoProcessing = false;
console.log(`${reader.reader.name} device attached`);
reader.on('card', card => {
console.log(`${reader.reader.name} card inserted`, card);
// Send custom APDU commands using reader.transmit()
});
});Example with MIFARE Ultralight tag:
reader.on('card', async card => {
try {
const data = await reader.read(4, 12);
console.log('Data read:', data.toString());
} catch (err) {
console.error('Error reading data', err);
}
try {
const text = 'Bright minds build code';
const buffer = Buffer.alloc(12, 0);
buffer.write(text);
await reader.write(4, buffer);
console.log('Data written');
} catch (err) {
console.error('Error writing data', err);
}
});Yes. It works with Electron and other Node.js environments that support native modules.
See Electron’s guide on native modules.
Yes. You’ll need to update your package.json and webpack.config.js per this issue comment.
No. The library is already transpiled to support Node.js 18+.
It supports from the version 18.x to the latest 25.x, including the current LTS on 22.x. Node.js uses the convention of having the even-numbered versions as stable releases and odd-numbered versions having experimental features, but even and odd-numbered version numbers are basically backwards compatible.
Ref: Official Node.js Release Plan
Yes. Use reader.read() and parse the raw bytes with TapTrack/NdefJS.
No. nfc-pcsclite depends on Node.js native bindings and PC/SC APIs, unavailable in mobile runtimes.
See explanation.
See instructions.
Set readClass to 0x00 in:
reader.read(blockNumber, length, blockSize, packetSize, 0x00);See discussion.
This library revives maintenance over an abandoned project. For a high-level API, see nfc-pcsc.
Released under the MIT License.