loading
Warning:
Chromium on Android only Web NFC is an experimental API implemented exclusively in Chromium-based browsers on Android devices with NFC hardware. It is unavailable on every desktop browser, on iOS, and in Firefox. On this machine the demos below will most likely report unsupported - check IsSupported first and keep every call inside a try/catch.
Note:
Permission and user gesture NFC requires a secure context (HTTPS), and the first scan triggers an nfc permission prompt. Scanning and writing must be initiated from a user gesture such as a button click.

Support check

IsSupported

Returns true when the runtime exposes NDEFReader. During prerender/SSR the check returns false rather than throwing, so defer it to OnAfterRenderAsync.

C#
@inject Bit.Butil.Nfc nfc

var supported = await nfc.IsSupported();
Live sample
support check output
Results will appear here when you interact with the samples.

Scan for tags

Scan

Starts listening for NDEF tags. Each tap delivers a typed NdefMessage - the tag's serial number plus its records (record type, MIME type, language, decoded text or raw bytes). Dispose the returned handle to stop scanning.

C#
private IAsyncDisposable? _scan;

_scan = await nfc.Scan(
    onReading: message =>
    {
        var serial = message.SerialNumber;
        foreach (var record in message.Records)
        {
            // record.RecordType: "text", "url", "mime", ...
            // record.Text: decoded payload for text records
        }
    },
    onError: error => { /* scan/read error message */ });

// stop scanning:
await _scan.DisposeAsync();
Live sample
scan output
Results will appear here when you interact with the samples.

Write a text record

WriteText

Writes a single NDEF text record to the next tag tapped against the device. The optional lang parameter sets the record's BCP-47 language tag; the optional id sets an application-defined record id.

C#
var ok = await nfc.WriteText("Hello from Butil!", lang: "en");
// ok == true when the record was written to the tapped tag
Live sample
Text
Language (optional)
write text output
Results will appear here when you interact with the samples.

Write a URL record

WriteUrl

Writes a single NDEF URL record to the next tag tapped against the device - a tag that most phones will open in the browser when scanned.

C#
var ok = await nfc.WriteUrl("https://bitplatform.dev");
Live sample
URL
write url output
Results will appear here when you interact with the samples.

API reference

Member
Signature
Description
IsSupported
ValueTask<bool> IsSupported()
True when the runtime exposes NDEFReader. Returns default (false) during prerender/SSR instead of throwing.
Scan
Task<IAsyncDisposable> Scan(Action<NdefMessage>? onReading, Action<string>? onError = null)
Starts scanning for NDEF tags. Dispose the returned handle to stop. Throws ArgumentException when both handlers are null.
WriteText
ValueTask<bool> WriteText(string text, string? lang = null, string? id = null)
Writes a single NDEF text record to the next tag tapped against the device.
WriteUrl
ValueTask<bool> WriteUrl(string url, string? id = null)
Writes a single NDEF URL record to the next tag tapped against the device.
DisposeAsync
ValueTask DisposeAsync()
Stops every active scan and releases the JS callback reference. Called automatically on scope/circuit teardown.
InvokeNdefReading
void InvokeNdefReading(Guid id, NdefMessage message)
JSInvokable interop plumbing for tag reads - not intended for app code.
InvokeNdefError
void InvokeNdefError(Guid id, string message)
JSInvokable interop plumbing for scan errors - not intended for app code.
NdefMessage.SerialNumber
string SerialNumber { get; set; }
The scanned tag's serial number.
NdefMessage.Records
NdefRecord[] Records { get; set; }
The NDEF records carried by the message: RecordType, MediaType, Id, Lang, Encoding, Text and raw Data.
An unhandled error has occurred. Reload 🗙