{"id":50124306,"url":"https://github.com/clusterm/ha-proxmark3","last_synced_at":"2026-05-26T03:02:37.311Z","repository":{"id":359807768,"uuid":"1247500639","full_name":"ClusterM/ha-proxmark3","owner":"ClusterM","description":"Home Assistant integration for Proxmark3 (Iceman): MF tag UID, block data, auto USB detect","archived":false,"fork":false,"pushed_at":"2026-05-23T14:29:32.000Z","size":569,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-23T16:14:06.280Z","etag":null,"topics":["hacs","home-assistant","mifare","nfc","proxmark3","rfid"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ClusterM.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["ClusterM"],"custom":["https://www.patreon.com/c/ClusterMeerkat","https://www.buymeacoffee.com/cluster","https://messenger.online.sberbank.ru/sl/Lnb2OLE4JsyiEhQgC","https://boosty.to/cluster"]}},"created_at":"2026-05-23T11:58:43.000Z","updated_at":"2026-05-23T14:27:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ClusterM/ha-proxmark3","commit_stats":null,"previous_names":["clusterm/ha-proxmark3"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ClusterM/ha-proxmark3","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClusterM%2Fha-proxmark3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClusterM%2Fha-proxmark3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClusterM%2Fha-proxmark3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClusterM%2Fha-proxmark3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ClusterM","download_url":"https://codeload.github.com/ClusterM/ha-proxmark3/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClusterM%2Fha-proxmark3/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33408490,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T18:09:33.147Z","status":"ssl_error","status_checked_at":"2026-05-23T18:09:31.380Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacs","home-assistant","mifare","nfc","proxmark3","rfid"],"created_at":"2026-05-23T19:01:14.376Z","updated_at":"2026-05-23T19:01:19.532Z","avatar_url":"https://github.com/ClusterM.png","language":"Python","funding_links":["https://github.com/sponsors/ClusterM","https://www.patreon.com/c/ClusterMeerkat","https://www.buymeacoffee.com/cluster","https://messenger.online.sberbank.ru/sl/Lnb2OLE4JsyiEhQgC","https://boosty.to/cluster"],"categories":[],"sub_categories":[],"readme":"# Proxmark3 for Home Assistant\n\nHome Assistant custom integration for [Proxmark3](https://github.com/RfidResearchGroup/proxmark3) (Iceman firmware). Polls for MIFARE / ISO14443-A tags and exposes UID, tag type, and optional block data as a sensor.\n\n## Features\n\n- Single Proxmark3 via USB serial (auto-detect)\n- Configurable MIFARE Classic keys and blocks to read\n- NDEF decoding (Ultralight/NTAG and optional MIFARE Classic) into a JSON `ntag` attribute\n- Device info (MCU, firmware, memory) cached while offline\n- Automatic reconnect when the device is unplugged\n- Options flow to tune keys, blocks, and poll intervals without re-adding the integration\n\n## Installation\n\n### HACS\n\n\u003e **Note:** The integration is not in the [default HACS repository](https://github.com/hacs/integration) yet. Until it is included, add this repo as a [custom repository](https://hacs.xyz/docs/faq/custom_repositories/) (category: **Integration**), then install **Proxmark3**.\n\n### Manual\n\nCopy `custom_components/proxmark3` into your Home Assistant `config/custom_components/` directory and restart Home Assistant.\n\n## Requirements\n\n- Proxmark3 with Iceman firmware ([RfidResearchGroup](https://github.com/RfidResearchGroup/proxmark3))\n- USB access from the Home Assistant host (Docker: pass through `/dev/ttyACM0` or the device by-id path)\n- Python packages `pyserial` and `proxmark3py` (installed automatically via manifest)\n\n## Configuration\n\nSetup is a short wizard (USB port is auto-detected):\n\n1. **Reading** — NDEF options, raw MIFARE Classic blocks toggle, poll intervals\n2. **Raw blocks** (only if enabled) — blocks 0–3 of MIFARE Classic sector 0\n3. **MIFARE Classic keys** (only if raw blocks enabled) — Key A presets for block reads\n\nUse **Options** later to change the same settings.\n\n**UID only:** leave everything off on screen 1. The sensor state is always the tag UID; `tag_type` is still reported.\n\n| Option | Tag types | Speed |\n|--------|-----------|-------|\n| Read NDEF (Ultralight / NTAG) | Type 2 tags | Fast |\n| Read NDEF on MIFARE Classic (slow) | Phone-formatted MIFARE Classic MAD/NDEF | Slow (several sector reads) |\n| Read raw blocks on MIFARE Classic | MIFARE Classic sector 0 blocks | Depends on enabled blocks + keys |\n\nMore enabled options increase read time on each new tag presentation.\n\n### NDEF\n\n- **Ultralight / NTAG:** enable **Read NDEF** — no keys required.\n- **MIFARE Classic (phone NDEF):** enable **Read NDEF on MIFARE Classic (slow)** separately. Uses MAD key (`a0a1a2a3a4a5`) and NDEF sector keys automatically (same as `hf mf ndefread`).\n\n#### Writing NDEF (phone is easiest)\n\nFor **Ultralight / NTAG** and **MIFARE Classic tags formatted as NDEF**, writing on a phone is usually the simplest option — no Proxmark3 required for programming.\n\n1. Install a free NFC app, e.g. **[NFC Tools](https://www.wakdev.com/en/apps/nfc-tools.html)** (Android / iOS).\n2. Choose **Write** → add a record:\n   - **URL / URI** — links, `https://…`\n   - **Text** — plain text with language code\n   - **Custom** — other NDEF types supported by the app\n3. Hold the tag to the phone and write.\n4. In Home Assistant, enable **Read NDEF** (and **Read NDEF on MIFARE Classic** for MIFARE Classic tags), then verify the `ntag` attribute on `sensor.proxmark3_nfc_tag`.\n\nNFC Tools (and similar apps) produce standard NDEF that this integration parses into JSON. MIFARE Classic tags are written as MAD/NDEF automatically by the phone OS or app.\n\n**Example `ntag` values** (attribute is a JSON **string** containing an array):\n\n```json\n[{\"tnf\":\"well_known\",\"type\":\"U\",\"uri\":\"https://example.com/room/kitchen\"}]\n```\n\n```json\n[{\"tnf\":\"well_known\",\"type\":\"T\",\"language\":\"en\",\"text\":\"Kitchen light\"}]\n```\n\nMultiple records in one tag appear as several objects in the array.\n\n### Keys\n\nKeys appear on **screen 3** only when **Read raw blocks on MIFARE Classic** is enabled.\n\nThe integration reads **MIFARE Classic** blocks with **Key A**, trying keys **in the order** they appear in settings. It stops at the first key that works.\n\n| Preset | Hex | When to enable |\n|--------|-----|----------------|\n| Factory default | `ffffffffffff` | **Most blank or retail tags.** Default choice; enable this first. |\n| MAD key A | `a0a1a2a3a4a5` | Multi-application MAD sectors, some transport cards. |\n| NDEF | `d3f7d3f7d3f7` | NTAG / NDEF-formatted tags (often used with MAD). |\n| Null key | `000000000000` | Tags explicitly programmed with an all-zero key. |\n| Custom | 12 hex chars | Your own key; appended **after** the checked presets. |\n\n**Tips**\n\n- Start with **factory default only** for fastest reads.\n- Add more presets only if reads fail (`block_*` attributes are empty or missing while UID is present).\n- Put the most likely key first (order in the UI = try order).\n- Custom key is useful when you already know the sector key from `hf mf chk` / `hf mf autopwn` in the PM3 client.\n\nKeys are **not** used for UID detection, Ultralight/NTAG NDEF, or MIFARE Classic NDEF (those paths use built-in MAD/NDEF keys).\n\n### Raw blocks (MIFARE Classic, 0–3)\n\nEnable **Read raw blocks on MIFARE Classic** on screen 1, then pick blocks on screen 2.\n\nThe integration reads **blocks 0–3** (sector 0 on MIFARE Classic 1K). Block reading is **optional** — leave the toggle off for fastest UID-only polling.\n\n| Block | MIFARE Classic 1K (sector 0) | Typical use in automations |\n|-------|--------------------------------|----------------------------|\n| **0** | Manufacturer data, UID/BCC (partly read-only) | Read-only for most users; **do not write** without knowing the format |\n| **1** | User data | **Good default** — often used for custom bytes, counters, magic markers |\n| **2** | User data | Second user data block in sector 0 |\n| **3** | Sector trailer (Key A / access bits / Key B) | Advanced; contains keys and ACLs, not arbitrary user data |\n\n**How to use in Home Assistant**\n\n- Write a pattern to block 1 on the tag (see PM3 examples below), e.g. `A1B2C3D4…`.\n- Enable **block 1** (and the correct key) in integration options.\n- Trigger automations on `sensor.proxmark3_nfc_tag` state (UID) and/or `block_1` attribute.\n\n**Tag types**\n\n| Tag type | Raw blocks 0–3 | NDEF |\n|----------|----------------|------|\n| MIFARE Classic 1K / 4K / Mini | Yes — with keys | Optional (**MIFARE Classic NDEF**, slow) |\n| MIFARE Ultralight / NTAG | No (MIFARE Classic-only toggle) | Optional (**Read NDEF**, fast) |\n| MIFARE DESFire, Java cards, random ISO14443-A | **No** | **No** |\n\nDisable unused blocks to speed up polling (each block is a separate read).\n\n**Block 0** on MIFARE Classic holds manufacturer bytes and UID-related data (often only part of the block is writable). Writing garbage there can corrupt the tag identity or make it unreadable. On Ultralight/NTAG, page 0 is similarly reserved (UID, lock bits). Treat block/page 0 as **read-only** unless you know exactly what you are changing.\n\n**Block 3** on MIFARE Classic is the sector trailer (keys and access bits) — see warnings in the writing section below.\n\n### Intervals\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| Poll interval | 0.05 s | Delay when idle (no tag / tag held). Lower = more responsive, more USB traffic. |\n| Reconnect interval | 5 s | Delay between attempts when the device is unplugged or the port is missing. |\n\n## Sensor\n\n| State | Description |\n|-------|-------------|\n| UID hex string | Tag on the reader |\n| `unknown` / empty | No tag present |\n| unavailable | Proxmark3 disconnected (device info still cached on the device page) |\n\n**Attributes:** `tag_type`, `block_0` … `block_3` (when raw MIFARE Classic blocks are enabled), `ntag` (JSON array of decoded NDEF records), plus cached `bootrom`, `compiler`, `fpga`, `memory` when known.\n\n`ntag` is filled when **Read NDEF** and/or **Read NDEF on MIFARE Classic** matches the detected tag type.\n\nDefault entity id is usually `sensor.proxmark3_nfc_tag` (depends on your device name).\n\n## Writing raw blocks (Proxmark3 client)\n\nUse the Iceman **client** (`pm3` / `proxmark3`) when you need **raw hex bytes** in MIFARE Classic blocks — not for everyday NDEF (use a phone; see above). Stop Home Assistant polling or unload the integration while writing, so nothing else holds the serial port.\n\n**Read block 1 (verify):**\n\n```text\nhf mf rdbl --blk 1 -k FFFFFFFFFFFF\n```\n\n**Write 16 bytes to block 1** (factory key, sector 0):\n\n```text\nhf mf wrbl --blk 1 -k FFFFFFFFFFFF -d 0102030405060708090a0b0c0d0e0f\n```\n\n**Write ASCII marker** (e.g. `HA` + padding to 16 bytes):\n\n```text\nhf mf wrbl --blk 1 -k FFFFFFFFFFFF -d 4841FFFFFFFFFFFFFFFFFFFFFFFFFFFF\n```\n\n**Ultralight / NTAG page 4** (user area often starts at page 4; pages 0–3 are reserved — integration still reads 0–3 if enabled):\n\n```text\nhf mf wrbl --blk 4 -d 0102030405060708090a0b0c0d0e0f\n```\n\nDo **not** write **block 0** or **block 3** on MIFARE Classic unless you understand the data layout. Block 0 carries manufacturer/UID-related data; block 3 is the sector trailer (keys and access conditions). A bad write to either can brick the tag or the whole sector. On Ultralight/NTAG, avoid writing pages 0–2 for the same reason — use page 4+ for user data, or prefer **NDEF via NFC Tools** instead of raw page writes.\n\n## Example automations\n\nAdjust `entity_id` / `notify.*` to match your setup.\n\n### UID and MIFARE Classic block 1\n\nNotify when a tag is placed on the reader (UID + block 1). Requires **Read raw blocks on MIFARE Classic** and block 1 enabled.\n\n```yaml\nalias: NFC Tag (UID + block)\ndescription: \"\"\ntriggers:\n  - trigger: state\n    entity_id:\n      - sensor.proxmark3_nfc_tag\nconditions:\n  - condition: not\n    conditions:\n      - condition: state\n        entity_id: sensor.proxmark3_nfc_tag\n        state:\n          - unknown\n          - unavailable\nactions:\n  - action: notify.persistent_notification\n    data:\n      title: NFC Tag\n      message: \u003e-\n        Detected NFC tag, ID={{ states('sensor.proxmark3_nfc_tag') }},\n        block_1={{ state_attr('sensor.proxmark3_nfc_tag', 'block_1') }}\nmode: single\n```\n\nTo react only to a specific payload in block 1, add a template condition on `state_attr('sensor.proxmark3_nfc_tag', 'block_1')`.\n\n### NDEF (URL or text from `ntag` JSON)\n\nRequires **Read NDEF** and/or **Read NDEF on MIFARE Classic**. The `ntag` attribute is a JSON string; parse it with the `from_json` filter.\n\n**Open a URL from the first NDEF record** (e.g. tag written with NFC Tools → URL record):\n\n```yaml\nalias: NFC Tag NDEF URL\ndescription: \"\"\ntriggers:\n  - trigger: state\n    entity_id: sensor.proxmark3_nfc_tag\n    attribute: ntag\nconditions:\n  - condition: template\n    value_template: \u003e-\n      {% set raw = state_attr('sensor.proxmark3_nfc_tag', 'ntag') %}\n      {{ raw not in [none, ''] }}\nactions:\n  - variables:\n      ndef_uri: \u003e-\n        {% set records = state_attr('sensor.proxmark3_nfc_tag', 'ntag') | from_json %}\n        {{ records[0].uri | default('') }}\n  - condition: template\n    value_template: \"{{ ndef_uri != '' }}\"\n  - action: notify.persistent_notification\n    data:\n      title: NFC tag URL\n      message: \"NDEF link: {{ ndef_uri }}\"\nmode: single\n```\n\n**Run different actions by NDEF text** (e.g. tag with text `Kitchen` / `Bedroom` from NFC Tools):\n\n```yaml\nalias: NFC Tag NDEF text room\ndescription: \"\"\ntriggers:\n  - trigger: state\n    entity_id: sensor.proxmark3_nfc_tag\n    attribute: ntag\nconditions:\n  - condition: template\n    value_template: \u003e-\n      {% set raw = state_attr('sensor.proxmark3_nfc_tag', 'ntag') %}\n      {% if raw in [none, ''] %}\n        false\n      {% else %}\n        {% set records = raw | from_json %}\n        {{ records | selectattr('text', 'defined') | list | length \u003e 0 }}\n      {% endif %}\nactions:\n  - choose:\n      - conditions:\n          - condition: template\n            value_template: \u003e-\n              {% set records = state_attr('sensor.proxmark3_nfc_tag', 'ntag') | from_json %}\n              {{ records[0].text | default('') == 'Kitchen' }}\n        sequence:\n          - action: light.turn_on\n            target:\n              entity_id: light.kitchen\n      - conditions:\n          - condition: template\n            value_template: \u003e-\n              {% set records = state_attr('sensor.proxmark3_nfc_tag', 'ntag') | from_json %}\n              {{ records[0].text | default('') == 'Bedroom' }}\n        sequence:\n          - action: light.turn_on\n            target:\n              entity_id: light.bedroom\nmode: single\n```\n\n**Reusable template** — first URL or text from any record:\n\n```jinja2\n{% set raw = state_attr('sensor.proxmark3_nfc_tag', 'ntag') %}\n{% if raw in [none, ''] %}\n  none\n{% else %}\n  {% set records = raw | from_json %}\n  {{ records[0].uri | default(records[0].text | default(none)) }}\n{% endif %}\n```\n\n\n## License\n\nGPLv3 License\n\n## Support the Developer and the Project\n\n* [GitHub Sponsors](https://github.com/sponsors/ClusterM)\n\n* [Patreon](https://www.patreon.com/c/ClusterMeerkat)\n\n* [Buy Me A Coffee](https://www.buymeacoffee.com/cluster)\n\n* [Sber](https://messenger.online.sberbank.ru/sl/Lnb2OLE4JsyiEhQgC)\n\n* [Donation Alerts](https://www.donationalerts.com/r/clustermeerkat)\n\n* [Boosty](https://boosty.to/cluster)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclusterm%2Fha-proxmark3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclusterm%2Fha-proxmark3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclusterm%2Fha-proxmark3/lists"}