# NFC Reader

> Read and write NFC tags in Android Chrome. Text, URL, Wi-Fi. No app. Overwrite cannot be undone; makeReadOnly is irreversible. Backup first. Nothing uploaded.

- URL: https://bytescope.dev/en/nfc-reader/
- Locale: en · Also: [ja](https://bytescope.dev/ja/nfc-reader.md) · [zh-Hant](https://bytescope.dev/zh-Hant/nfc-reader.md)
- Runs: Nothing is uploaded or logged. Tag bytes stay in this tab and are gone when you leave.
- Requires: Chrome on Android only (Web NFC). No desktop browser and no iOS browser exposes NFC to web pages.
- Updated: 2026-09-08

## What it does

This page is an NFC tag reader online, and a way to write an NFC tag without an app. It talks to the tag in this tab through Web NFC (`NDEFReader`). Nothing is uploaded. It runs in Android Chrome, on HTTPS, after a tap. iPhone and desktop visitors still get the about text, the FAQ, and an honest support matrix — the tool does not vanish on them.

### What a tag can hold

A `reading` event carries `serialNumber` and `message.records`. Each record has `recordType`, `mediaType`, `id`, `data` (a DataView), `encoding`, `lang`. `text` shows the string plus lang and encoding. `url` / `absolute-url` become a link only for `http:`, `https:`, `mailto:`, `tel:` and a short whitelist — `javascript:`, `data:`, `vbscript:` stay plain text and are marked unsafe. `mime` is `mediaType` plus a hex dump in the hex-editor language. `application/vnd.wfa.wsc` is a Wi-Fi WPS credential: SSID, authentication, encryption; the Network Key is hidden until you tap, and the page warns that the password will appear in the clear. `unknown` and external types (`example.com:foo`) are hex. Bytes this page cannot name stay hex. It will not guess a type.

### Writing overwrites. Locking is forever

`ndef.write(message, { overwrite: true })` replaces what is on the tag. That payload is gone unless you already exported a backup from a read. `ndef.makeReadOnly()` permanently locks the tag. There is no rescue — not a factory reset, not a programmer. Both actions stay behind a closed danger panel, then an Arm → Confirm step copied from the fuse writer. Locking also requires typing `LOCK`. Scan never writes. Write never runs inside the read path.

### Waiting is not empty

Holding the phone out and getting nothing yet is "not read", not "the tag is empty". An empty NDEF message (zero records) is a separate result. `readingerror` is "this tag could not be read". `NotAllowedError` is permission or a locked tag, not a missing tag. If `permissions.query({ name: "nfc" })` throws, that is `unknown`, never `denied`.

### Android Chrome only

Web NFC is specified for Android Chrome. Desktop Chrome has no `NDEFReader`. iOS Safari has none. Edge on Android is untested here and marked that way. Feature detection runs after mount (`"NDEFReader" in window`). Trust the live row, not a version table.

## Limits

Does not read bank cards, transit cards or passports, and does not clone tags; it reads and writes NDEF records on NFC Forum tags.

ndef.makeReadOnly() permanently locks this tag. It can never be written again. This is irreversible.

## FAQ

### Which browsers can read an NFC tag here?

Android Chrome, with HTTPS and a tap. Desktop Chrome, Firefox, Safari (including iPhone) have no Web NFC. This page still renders about, FAQ and the matrix on those browsers — it does not return null.

### Do you upload what is on the tag?

No. Bytes stay in this tab. There is no server round-trip of the payload. Export backup is a file you save locally. Closing the page drops the snapshot.

### I tapped Scan and nothing happened. Is the tag empty?

No. That is the waiting state: no `reading` event yet. An empty tag is a `reading` event with no records. Those two sentences are not interchangeable on this page.

### What does makeReadOnly do? Can I undo it?

It permanently locks the tag. No further writes, ever. There is no rescue. This page will not soften that. You must open the danger panel, type LOCK, Arm, then Confirm. Do not use it unless you intend to brick writes on that tag.

### A URL on the tag starts with javascript:. Is it a link?

No. Only a whitelist of schemes becomes an `<a href>`. `javascript:`, `data:`, `vbscript:`, encoded variants, and protocol-relative `//` stay text and are labelled unsafe. Tag content is untrusted input: no `innerHTML`, no `eval`.

### The tag has my Wi-Fi password. Will this page show it?

The Network Key starts hidden. A tap reveals it, and a warning says the password will be on screen in the clear. Export backup includes it because a backup that omits the key is not a backup. Treat the file as a secret.

## Related tools

- [Web ADB Toolkit](https://bytescope.dev/en/web-adb.md) — Same audience: talk to an Android phone from this tab, over USB.
- [Hex Viewer / Editor](https://bytescope.dev/en/hex-editor.md) — Same offset / 16-byte / ASCII language, for a file instead of a tag.
- [Clipboard Inspector](https://bytescope.dev/en/clipboard-inspector.md) — Inspect untrusted bytes that never leave this tab — clipboard, not NFC.
