Python NFC Programming Guide
nfcpy Library for Desktop Applications
Using the nfcpy library for NFC programming in Python. Covers tag discovery, NDEF operations, card emulation, and LLCP peer-to-peer.
Python NFC Programming Guide: nfcpy Library
nfcpy by Stephen Tiedemann is the most mature Python library for NFC reader hardware, supporting contactless cards, tag operations, and peer-to-peer sessions on Linux and macOS. It communicates with USB, SPI, and UART-connected NFC reader ICs including the PN532, PN533, RCS380, and ACR122U.
Installation
pip install nfcpy
# Optionally for USB device detection:
pip install libusb1 pyserial
On Linux, grant your user permission to access USB without sudo:
sudo adduser $USER plugdev
# Create udev rule for ACR122U or similar
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="072f", MODE="0666", GROUP="plugdev"' \
| sudo tee /etc/udev/rules.d/93-nfc.rules
sudo udevadm control --reload-rules
Connecting to a Reader
import nfc
def connected(tag):
print(f"Tag found: {tag}")
return True # return False to stop after one tag
with nfc.ContactlessFrontend('usb') as clf:
clf.connect(rdwr={'on-connect': connected})
nfc.ContactlessFrontend accepts:
- 'usb' — auto-detect first USB NFC reader
- 'usb:072f:2200' — specific vendor/product IDs
- 'tty:S0:pn532' — serial UART device
- 'i2c:0' — I2C bus (Raspberry Pi)
The PN532 over I2C is the most common setup for Raspberry Pi projects. See NFC Arduino and Raspberry Pi for wiring.
Reading NDEF from a Tag
import nfc
import ndef
def on_connect(tag):
if tag.ndef is None:
print("Tag has no NDEF content")
return False
print(f"NDEF version: {tag.ndef.version}")
print(f"Capacity: {tag.ndef.capacity} bytes")
print(f"Writeable: {tag.ndef.is_writeable}")
for record in tag.ndef.records:
if isinstance(record, ndef.UriRecord):
print(f"URI: {record.iri}")
elif isinstance(record, ndef.TextRecord):
print(f"Text ({record.language}): {record.text}")
elif isinstance(record, ndef.SmartposterRecord):
print(f"SmartPoster URI: {record.resource}")
else:
print(f"Record type: {record.type!r}")
return True
with nfc.ContactlessFrontend('usb') as clf:
clf.connect(rdwr={'on-connect': on_connect})
The tag.ndef attribute is None if the tag has no NDEF capability container or is not NDEF-formatted. All record types map to Python objects via the companion ndeflib package (pip install ndeflib).
Writing NDEF to a Tag
import nfc
import ndef
def write_url(tag):
if tag.ndef is None:
print("Cannot write: no NDEF support")
return False
if not tag.ndef.is_writeable:
print("Tag is write-protected — check [lock-bits](/glossary/lock-bits/)")
return False
records = [ndef.UriRecord("https://nfcfyi.com")]
tag.ndef.records = records
print(f"Written {len(records)} record(s)")
return False # stop after write
with nfc.ContactlessFrontend('usb') as clf:
clf.connect(rdwr={'on-connect': write_url})
Low-Level Tag Access
For operations beyond NDEF — reading raw memory blocks, setting password-protection, or writing otp bytes — access the tag's underlying type object:
def raw_access(tag):
# Type 2 tag (e.g. NTAG213/215/216)
if isinstance(tag, nfc.tag.tt2.Type2Tag):
# Read 4 bytes at page 4 (user memory starts at page 4)
data = tag.read(4)
print(f"Page 4: {data.hex()}")
# Write 4 bytes to page 4
tag.write(4, bytearray([0x01, 0x02, 0x03, 0x04]))
# Type 4 tag (e.g. DESFire)
elif isinstance(tag, nfc.tag.tt4.Type4Tag):
response = tag.send_apdu(0x00, 0xA4, 0x04, 0x00)
print(f"APDU response: {response.hex()}")
return False
NTAG Password Protection
def set_password(tag):
if not isinstance(tag, nfc.tag.tt2_nxp.NTAG215):
return False
# Write 4-byte password to page 85 (0x55)
tag.write(0x55, bytearray([0x41, 0x42, 0x43, 0x44]))
# Write 2-byte PACK to page 86
tag.write(0x56, bytearray([0xAA, 0xBB, 0x00, 0x00]))
# Set AUTH0 in CFG0 (page 83): protect from page 4 onwards
cfg0 = bytearray(tag.read(0x53))
cfg0[3] = 0x04 # AUTH0 = page 4
tag.write(0x53, cfg0)
print("Password set")
return False
Always test password configurations with a test tag before deploying. Incorrect access-control-bits can permanently lock a tag.
Card Emulation and Peer-to-Peer
nfcpy supports card-emulation-mode on readers with hardware support (e.g. RC-S380):
def on_startup(target):
target.sensf_res = bytearray.fromhex("0112FC..." )
return target
def on_connect(llc):
# LLCP logical link control
print("P2P connected")
return True
with nfc.ContactlessFrontend('usb') as clf:
clf.connect(llcp={'on-startup': on_startup, 'on-connect': on_connect})
llcp and snep are used for peer-to-peer data exchange and legacy Android Beam compatibility.
Batch Tag Processing Script
import nfc, ndef, time
tags_processed = 0
def process_tag(tag):
global tags_processed
if tag.ndef:
for record in tag.ndef.records:
if isinstance(record, ndef.UriRecord):
print(f"[{tags_processed:04d}] {record.iri}")
tags_processed += 1
return True # keep looping
with nfc.ContactlessFrontend('usb') as clf:
print("Place tags on reader. Ctrl+C to stop.")
try:
clf.connect(rdwr={'on-connect': process_tag, 'interval': 0.1})
except KeyboardInterrupt:
print(f"Processed {tags_processed} tags")
The interval parameter (seconds) controls how quickly the reader polls for new tags after the previous one is removed. Use 0.1 s for rapid batch processing.
Supported Reader Hardware
| Reader | Interface | Notes |
|---|---|---|
| ACR122U | USB | Most common; PN532 inside |
| Identiv uTrust 3700F | USB | ISO 15693 + 14443 |
| Sony RC-S380 | USB | P2P / HCE capable |
| PN532 breakout | SPI / I2C / UART | Raspberry Pi / Arduino |
| SCL3711 | USB | CCID compliant |
Use the NFC Reader Modules Compared guide for IC-level selection.
See also: NFC Arduino and Raspberry Pi | ESP32 NFC Development | NDEF Specification Deep Dive | NFC Tag Types Explained
자주 묻는 질문
Our guides cover a range of experience levels. Getting Started guides are written for beginners with no prior NFC knowledge. Programming guides target developers integrating NFC into mobile apps or embedded systems. Security guides are for engineers designing secure NFC deployments for payments, access control, or authentication.
Most guides require only an NFC-enabled smartphone (iPhone 7+ or any modern Android device) and a few NFC tags (NTAG213 or NTAG215 recommended for beginners, available for under $1 each). Advanced guides may reference USB NFC readers like the ACR122U or Proxmark3 for development and testing.
Yes. Programming guides include code examples for Android (Kotlin/Java with the Android NFC API), iOS (Swift with Core NFC), and web-based tools (Web NFC API for Chrome on Android). All code samples are tested and include inline comments explaining each step.