Offline Python SDK for TigerTag RFID material identification
Project description
TigerTag Python SDK
Offline Python SDK for TigerTag RFID material identification.
TigerTag is the world's most widely deployed open-source RFID protocol for manufacturing material identification — with over 2 million chips deployed worldwide. Adopted by major brands including eSun, Rosa3D, Sunlu, R3D, Landu and many more. Currently covers filament and resin. Designed to extend to any physical material (sheet goods, wood, PMMA, metals, composites…). All material data is stored directly on the NTAG chip — 100% offline.
Industry adoption
TigerTag is the #1 RFID material identification protocol in the 3D printing industry and the only open-source standard with broad manufacturer adoption at scale.
| Metric | Value |
|---|---|
| Chips deployed worldwide | 2 000 000+ |
| Filament / resin brands | eSun · Rosa3D · Sunlu · R3D · Landu · and more |
| Connected printers & slicers | Snapmaker · Bambu Lab · FlashForge · Elegoo · Creality · and more coming |
| Exclusive integrations | HueForge (Transmission Distance) · TD1s by Ajax (filament manager) |
| Cost for end users | 100% free — protocol, SDK, Studio Manager, mobile apps |
| Protocol status | Open source (GPLv3) — free to implement for manufacturers |
| Hardware | Tiger Scale (DIY ~30 € open-source) · TigerTag Pod (read/write desktop + mobile) |
| Ecosystem maturity | Desktop app · Mobile app · Pod · DIY scale · Firebase · Python SDK |
| Chip compatibility | NTAG213 · NTAG215 · NTAG216 · any ISO 14443-3 compatible |
What makes TigerTag unique
1 — Proof of authenticity (ECDSA-P256)
TigerTag is the only material RFID protocol to offer cryptographic proof of authenticity. Each signed chip carries an ECDSA-P256 signature that binds the chip UID to the product data. Any reader — including this SDK — can verify the signature fully offline, with no server call:
result = tag.verify() # ✅ VALID — chip is genuine and untampered
# ❌ INVALID — data has been modified or chip is cloned
# ⬜ NOT SIGNED — unsigned Maker tag (verification not required)
No other RFID material protocol provides on-chip cryptographic authentication at this level.
2 — Chips reusable forever
TigerTag chips are never write-locked. Once a spool is finished, the chip gets a second life:
- Erase and reprogram as a fresh TigerTag for a new spool:
TigerTag.erase() - Reprogram with any NFC / NDEF standard for a completely different use case
- Use as a plain NTAG tag in any NFC-capable application
Zero electronic waste. The chip is a permanent, reusable asset — not single-use packaging. No competing protocol offers this combination of authentication and unlimited reusability.
3 — Remote update by the manufacturer (TigerTag+)
TigerTag+ is the only material RFID protocol with remote over-the-air update capability for manufacturers. When a filament or material brand publishes improved print settings, corrected temperatures, or updated material data to the TigerTag cloud API, every chip already deployed in the field can receive those updates — without recalling a single spool:
# On any reader / printer / slicer that uses this SDK:
patched_tag, changes = tag.patch_from_api() # fetch latest manufacturer data + apply to chip
print(f"{len(changes)} field(s) updated by manufacturer")
# Or inspect what changed before applying:
diffs = tag.diff_api()
for d in diffs:
print(f"{d.field}: chip={d.chip_value!r} → manufacturer={d.api_value!r}")
The update is manufacturer-driven and cryptographically scoped — only the product data fields can change. The chip UID and signature remain protected. No other RFID material protocol gives manufacturers this level of post-deployment control over their product data.
4 — Native HueForge integration
TigerTag is the only RFID protocol natively integrated with HueForge. The TD (Transmission Distance) value is stored directly on the chip and read by HueForge without any manual entry. It is also the only protocol supported by TD1s by Ajax, the open-source filament manager.
Hardware ecosystem
| Device | What it does | Price |
|---|---|---|
| Tiger Scale | Open-source DIY ESP32 smart scale — reads the TigerTag, weighs the spool, updates measure_available in real time |
~30 € in parts |
| TigerTag Pod | Plug-and-play NFC reader/writer — read and write chips from your desktop (via TigerTag Studio Manager) or from your phone (via TigerTag RFID Connect on iOS and Android) | — |
The TigerTag Pod works with the TigerTag RFID Connect app (iOS + Android) for full mobile read/write access — no soldering, no setup, just plug in and scan.
Everything is free for end users: the protocol, this SDK, TigerTag Studio Manager, the mobile apps, and all community tools. No subscription, no lock-in.
▶ Try the Playground
No NFC hardware required — explore the full SDK output directly in your browser.
# Start the dev server
python3 tools/server.py 7432
# Open in browser
open http://localhost:7432/tools/playground.html
The playground has three panels:
- Left — generate TigerTag / TigerTag+ / Init tags with presets or custom values
- Center — parsed output cards: Protocol, Material, Colors, Print Settings, Traceability, Cloud API
- Right — collapsible SDK panel:
pretty(),verify(),to_raw_dict(),to_dict(),raw_api(),diff_api()
Install
pip install tigertag # core only — stdlib, works fully offline
pip install tigertag[sync] # + requests (database auto-update)
pip install tigertag[verify] # + cryptography (ECDSA signature check)
pip install tigertag[full] # everything
Zero configuration. Zero network required on first run. Bundled reference databases ship with the package.
Quick start
from tigertag import TigerTag
tag = TigerTag.from_pages(uid, payload) # from your NFC SDK
print(tag.pretty()) # human-readable summary
print(tag.verify()) # ✅ VALID / ⬜ NOT SIGNED / ❌ INVALID
print(tag.to_dict()) # JSON-ready dict
That's it. Works immediately after pip install tigertag.
What is TigerTag?
TigerTag is an open-source RFID protocol that stores manufacturing material data directly on NFC chips (NTAG213 / NTAG215 / NTAG216, ISO 14443-3 compatible). No cloud dependency for reading — all data lives on the chip.
Tag types:
| Tag type | ID Product | Offline | Cloud |
|---|---|---|---|
| TigerTag (Maker) | 0xFFFFFFFF |
✅ full data on chip | — |
| TigerTag Init | 0x00000000 |
✅ blank template | — |
| TigerTag+ | numeric ID | ✅ full data on chip | ✅ API for live updates |
This SDK reads all three types identically. TigerTag+ cloud comparison (diff_api()) requires requests.
Protocol spec: github.com/TigerTag-Project/TigerTag-RFID-Guide
Constructors
| Method | Input | When to use |
|---|---|---|
TigerTag.from_pages(uid, payload) |
80 or 144 bytes + 7-byte UID | NFC SDK integration (recommended) |
TigerTag.from_dump(data) |
80 / 144 / 180 bytes | Binary dumps, ACR122U raw read |
TigerTag.from_file(path) |
path to .bin file |
Testing, offline batch processing |
from_pages is the primary constructor for production use. NFC SDKs always provide the UID as a separate property — pass it directly for full signature verification.
from_dump with 180 bytes (full chip dump including system pages) auto-extracts the 7-byte UID.
Input formats
from_pages(uid, payload) — NFC SDK workflow
NFC SDKs always expose the UID as a dedicated property. Pages 0–3 (system pages: lock bytes, capability container) are never part of the user data payload.
| Payload | Pages | UID | Verifiable |
|---|---|---|---|
| 144 bytes | 0x04–0x27 (user data + signature) | Required (7 bytes) | ✅ Yes |
| 80 bytes | 0x04–0x17 (user data, no signature) | Required (7 bytes) | N/A |
from_dump(data) — binary dump workflow
| Dump | Content | UID | Verifiable |
|---|---|---|---|
| 180 bytes | Full chip (pages 0–44, includes system pages) | Auto-extracted | ✅ Yes |
| 144 bytes | Partial dump (user data only, no system pages) | Not available | ❌ No |
| 80 bytes | User data only | Not available | N/A |
Key methods
# Read
tag.pretty(db=None, sig_result=None) -> str # human-readable summary
tag.to_dict(db=None) -> dict # JSON-serializable, all labels resolved
tag.to_raw_dict() -> dict # raw protocol fields, no resolution
tag.to_bytes(include_signature=False)-> bytes # re-serialize to chip bytes
tag.validate() -> list[str] # sanity check — returns list of warnings
tag.verify(db=None) -> SignatureResult
# Write (immutable — all return a new TigerTag)
TigerTag.create(**kwargs) -> TigerTag # build from scratch
TigerTag.as_init(uid) -> TigerTag # blank Init tag
TigerTag.erase() -> bytes # 80 zero bytes — write to chip to wipe
tag.patch(**kwargs) -> TigerTag # surgical field update
# Cloud (TigerTag+ only — requires requests)
tag.raw_api(db=None) -> dict | None # fetch live product data from API
tag.diff_api(api_data, db) -> list[ApiDiff] # compare chip vs API
tag.patch_from_api(api_data, db) -> tuple[TigerTag, list[ApiDiff]] # apply API values
tag.sync_db(db_path=None, force=False) -> list[str] # update reference databases
Key properties
tag.is_maker # True if id_product == 0xFFFFFFFF
tag.is_init # True if id_product == 0x00000000
tag.is_plus # True if id_product is a valid cloud ID
tag.is_signed # True if signature bytes are non-zero
tag.uid_hex # "04AABBCCDDEE11" or None
tag.color1_hex # "#FF3232"
tag.td_value # 12.5 (HueForge Transmission Distance)
tag.manufacturing_date# datetime (UTC)
tag.stock_percent # 75.0 or None
Write / CRUD operations
from tigertag import TigerTag
# Build a new tag from scratch
tag = TigerTag.create(
uid=bytes.fromhex("04A1B2C3D4E5F6"),
id_material=38219, # PLA
id_brand=19961, # Rosa3D
nozzle_temp_min=195,
nozzle_temp_max=230,
color1_r=255, color1_g=0, color1_b=0, color1_a=255,
measure=1000, id_unit=21,
)
# Blank TigerTag Init chip (ready for programming)
init_tag = TigerTag.as_init(uid=bytes.fromhex("04A1B2C3D4E5F6"))
# Erase a chip — write the returned 80 bytes to the NFC chip
blank_bytes = TigerTag.erase()
# Immutable surgical update — returns a new TigerTag, original unchanged
patched = tag.patch(nozzle_temp_min=200, dry_temp=55)
# TigerTag+ cloud sync
api_data = tag.raw_api() # fetch live product data
diffs = tag.diff_api(api_data) # what differs chip vs cloud?
patched_tag, applied = tag.patch_from_api() # apply all cloud values
print(f"{len(applied)} field(s) updated from cloud")
Protected fields — patch() raises ValueError if you try to modify: id_tigertag, id_product, uid, signature_r, signature_s.
ApiDiff
ApiDiff is a namedtuple (field, chip_value, api_value):
from tigertag import ApiDiff, TigerTag
tag = TigerTag.from_pages(uid, payload)
diffs = tag.diff_api()
for d in diffs:
print(f"{d.field}: chip={d.chip_value!r} → api={d.api_value!r}")
Fields compared: nozzle_min, nozzle_max, bed_min, bed_max, dry_temp, dry_time, type, material, brand, diameter, aspect_1, aspect_2, color_1, color_2, color_3, measure_g, measure_unit.
Signature verification
result = tag.verify() # fully autonomous — finds the public key from the bundled DB
result.ok # True only for VALID
result.status # "valid" | "invalid" | "unsigned" | "no_crypto" | "no_key" | "no_uid"
str(result) # "✅ VALID" | "❌ INVALID" | "⬜ NOT SIGNED" | "🔒 NO CRYPTO" | …
result.to_dict()# {"status": "valid", "ok": True, "detail": "…"}
| Status | Meaning |
|---|---|
VALID |
Signature matches — chip is authentic |
INVALID |
Signature present but does not match UID + data |
UNSIGNED |
No signature bytes — Maker tag or unverified |
NO_CRYPTO |
cryptography package not installed — run pip install tigertag[verify] |
NO_KEY |
No matching public key in database for this protocol version |
NO_UID |
UID not provided — cannot verify (use from_pages(uid, payload)) |
ECDSA-P256 verification uses the public key bundled in id_version.json — works fully offline.
Database (TigerTagDB)
from tigertag import TigerTagDB
db = TigerTagDB() # bundled database (offline, no network)
db = TigerTagDB(auto_sync=True) # check for updates on init
db = TigerTagDB("/path/to/custom/db") # custom database path
db.material(38219) # {"id": 38219, "label": "PLA", "density": 1.24, ...}
db.brand(1) # {"id": 1, "label": "Generic", ...}
db.version(0x01000001) # {"id": ..., "label": ..., "public_key": "-----BEGIN..."}
TigerTagDB.label(entry)# safe label extraction helper
Auto-update behavior
The SDK ships with bundled reference databases — works fully offline after pip install tigertag.
| Mode | Behavior |
|---|---|
| Default | Uses bundled JSONs — no network, always works |
TigerTagDB(auto_sync=True) |
Checks timestamps on init, downloads only changed files |
tag.sync_db(force=True) |
Forces full re-download |
tigertag --sync-only |
CLI sync, updates bundled database in place |
| Network failure | Caught silently — bundled databases used as fallback |
Sources: TigerTag API → GitHub mirror (automatic fallback).
NFC SDK integration
from_pages() accepts exactly what NFC SDKs provide:
# Android (NfcA / MifareUltralight)
uid = tag.id # ByteArray → bytes
payload = mifare.readPages(4, 39) # 144 bytes
# iOS (CoreNFC)
uid = tag.identifier # Data → bytes
payload = tag.readNDEF(...) # pages 4–39
# Flutter (flutter_nfc_kit)
uid = bytes.fromhex(tag.id)
payload = await FlutterNfcKit.readBlock(4, length=144)
# Python nfcpy / ACR122U
uid = tag.identifier # bytes
payload = tag.read(4, 36) # 36 pages × 4 bytes = 144 bytes
tag = TigerTag.from_pages(uid, payload)
result = tag.verify() # fully autonomous
ACR122U — full example (nfcpy)
pip install nfcpy "tigertag[verify]"
import nfc
from tigertag import TigerTag
def on_connect(tag):
uid = tag.identifier # 7 bytes — provided directly by nfcpy
payload = tag.read(4, 36) # 36 pages × 4 bytes = 144 bytes
tt = TigerTag.from_pages(uid, payload)
print(tt.pretty())
print(tt.verify()) # ✅ VALID / ⬜ NOT SIGNED / ❌ INVALID
return True
with nfc.ContactlessFrontend("usb") as clf:
clf.connect(rdwr={"on-connect": on_connect})
See examples/integrate_nfc_sdk.py for all platforms (Android, iOS, Flutter, Arduino).
Chip memory layout
CLI
tigertag dump.bin # parse + human-readable output
tigertag dump.bin --json # output as JSON
tigertag dump.bin --raw # raw protocol fields, no DB lookup
tigertag --sync-only # update reference databases and exit
tigertag --version # show SDK version
python -m tigertag dump.bin # same, via module runner
Standalone single-file usage
For projects where you can't add a dependency — drop parse_tigertag.py directly:
from parse_tigertag import TigerTag
tag = TigerTag.from_dump(open("dump.bin", "rb").read())
tag.sync_db() # auto-download databases (requires requests)
print(tag.pretty())
parse_tigertag.py is a complete standalone copy — no tigertag/ package required.
TigerTag ecosystem
Official hardware
| Device | Description | Cost |
|---|---|---|
| TigerTag Pod | Plug-and-play NFC reader/writer — connects to desktop (Studio Manager) or phone (RFID Connect app). Read and write chips with no soldering, no setup. | — |
| Tiger Scale | Open-source DIY ESP32 smart scale — reads the tag on scan, weighs the spool, and updates measure_available on the chip in real time. Full BOM and firmware available. |
~30 € in parts |
Official software
| Tool | Platform | Description |
|---|---|---|
| TigerTag-RFID-Guide | Spec | Open protocol specification |
| TigerTag-SDK-Python | Python | This SDK — parse, verify, write, diff |
| TigerTag Studio Manager | Windows / macOS / Linux | Open-source desktop inventory manager — works with TigerTag Pod and ACR122U |
| TigerTag RFID Connect | iOS | Official mobile app — read/write via TigerTag Pod |
| TigerTag RFID Connect | Android | Official mobile app — read/write via TigerTag Pod |
| TigerTag Firebase Integration | Cloud | Firebase backend integration example |
| Tiger Scale | ESP32 firmware | Open-source firmware for the DIY smart scale |
Community integrations: OpenRFID · Home Assistant · Snapmaker U1 firmware · TD1s by Ajax
License
Open source: GNU General Public License v3.0 — see LICENSE.md
Commercial OEM licensing: contact licensing@tigertag.io
Protocol spec: github.com/TigerTag-Project/TigerTag-RFID-Guide
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tigertag-1.1.1.tar.gz.
File metadata
- Download URL: tigertag-1.1.1.tar.gz
- Upload date:
- Size: 50.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7626d8d6999c2d496018d6d99006a13d7bb1ad873da178a886afd2a3d775cc1
|
|
| MD5 |
107214e3bb0347c002ba40e839c055c6
|
|
| BLAKE2b-256 |
95b39f103244fb36b13a5b999c5b3a4bdcd97774c997366a28aabf36847fe58a
|
Provenance
The following attestation bundles were made for tigertag-1.1.1.tar.gz:
Publisher:
publish.yml on TigerTag-Project/TigerTag-SDK-Python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tigertag-1.1.1.tar.gz -
Subject digest:
f7626d8d6999c2d496018d6d99006a13d7bb1ad873da178a886afd2a3d775cc1 - Sigstore transparency entry: 1588061935
- Sigstore integration time:
-
Permalink:
TigerTag-Project/TigerTag-SDK-Python@754e0424fa5978d82772949f81535dfb3154d758 -
Branch / Tag:
refs/tags/v1.1.1 - Owner: https://github.com/TigerTag-Project
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@754e0424fa5978d82772949f81535dfb3154d758 -
Trigger Event:
release
-
Statement type:
File details
Details for the file tigertag-1.1.1-py3-none-any.whl.
File metadata
- Download URL: tigertag-1.1.1-py3-none-any.whl
- Upload date:
- Size: 42.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee58e019882d353e60a34ab1ac2a727ba24fce05c872fffd4a42b117140aba30
|
|
| MD5 |
2c2ddb7f6820672bfd7d2e05a9d9a589
|
|
| BLAKE2b-256 |
84f5e3a80b9f4a129a1d526630c0a5d5bb614db14d72e32399e23ccee2dda8bf
|
Provenance
The following attestation bundles were made for tigertag-1.1.1-py3-none-any.whl:
Publisher:
publish.yml on TigerTag-Project/TigerTag-SDK-Python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tigertag-1.1.1-py3-none-any.whl -
Subject digest:
ee58e019882d353e60a34ab1ac2a727ba24fce05c872fffd4a42b117140aba30 - Sigstore transparency entry: 1588061980
- Sigstore integration time:
-
Permalink:
TigerTag-Project/TigerTag-SDK-Python@754e0424fa5978d82772949f81535dfb3154d758 -
Branch / Tag:
refs/tags/v1.1.1 - Owner: https://github.com/TigerTag-Project
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@754e0424fa5978d82772949f81535dfb3154d758 -
Trigger Event:
release
-
Statement type: