Articles · How-To GuidesUpdated October 2026

Add NFC to an app and the awkward platform is iOS, where reading a tag needs an entitlement, not a permission.

Add NFC to an app and you do two different jobs. To read NFC tags on iOS, turn on the Near Field Communication Tag Reading capability for your target. That writes the com.apple.developer.nfc.readersession.formats entitlement and adds the feature to your App ID. Then add an NFCReaderUsageDescription string to Info.plist. On Android you add one manifest line, android.permission.NFC, at protection level normal, so nobody is asked anything. Every name here comes from Apple's and Google's own documentation, read on 3 October 2026. Wider context: the development guide.

Then the fact that costs a day. None of this runs in a simulator or an emulator. An NFC tag reading app needs a real phone and a real tag from the first test.

Check which gates apply to you

The short version

iOS gates the radio, Android gates who gets the tap.

Apple decides whether your app may touch the NFC hardware at all, and decides before you ship. Google hands it over on a normal permission, then rules on which app gets woken when a tag comes near.

So the iOS work is front loaded and administrative. The Android work sits in tag dispatch, intent filters and a user facing allow list. Both are easy to get wrong from an old tutorial.

What each platform asks you for

Start with iOS, because iOS can stop you. Apple's Core NFC sample gives two setup steps. Turn on the Near Field Communication Tag Reading capability for the target, which adds the Near Field Communication Tag Reader Session Formats entitlement to the entitlements file. Then add NFCReaderUsageDescription to Info.plist, a string saying why you need the reader. Apple is blunt about the second step. Without the key, the app exits when it tries to read a tag.

The entitlement key is com.apple.developer.nfc.readersession.formats and its value is an array of strings. Apple's page lists TAG, which allows read and write access using NFCTagReaderSession, and says to add it by enabling the capability in Xcode. No form, no wait. For ISO 7816 tags, list your application identifiers in the ISO7816 application identifiers for NFC Tag Reader Session key.

Two Core NFC limits catch people. It is unavailable in app extensions, so a widget cannot scan. And only one reader session can be active at a time, the rest queued first in, first out. Check the readingAvailable property before showing a scan button, because Apple's overview publishes no list of supported iPhone models.

Apple, Building an NFC Tag-Reader App, Core NFC documentation (read 3 October 2026)

Which gate applies to what you are building

The gate is not one gate. Reading an NDEF tag, reading a protocol specific tag, reading with no app in the foreground and acting like a card are four separate problems. Only the first two share a declaration. Ask the cheaper question first, too: to identify an object someone is holding, a printed code and the camera need no entitlement at all, which is why add qr code scanner is a shorter page than this one.

NFC earns its place when the tag must work without line of sight, survive handling, or be rewritten in the field. If you want a two way link to a nearby device instead, that is a different radio, and add bluetooth covers it.

Pick your jobs

Which gates apply to you

Tick what the app has to do. Every line below is taken from Apple's or Google's own developer documentation, read on 3 October 2026.

Tick a job

Whatever you tick, none of it runs in a simulator or an emulator. NFC needs the radio.

Android hands you the radio, then changes who gets the tap

On Android the permission is the dull part. android.permission.NFC arrived in API level 9. It allows applications to perform I/O operations over NFC, at protection level normal: install time, no dialog, nothing to refuse. Add a uses-feature element for android.hardware.nfc and Google Play shows the app only to devices with the hardware. Leave it out and check whether getDefaultAdapter returns null.

What you actually build is an intent filter. Tag dispatch parses the tag, works out a MIME type or URI, and starts an activity. Three actions exist, highest priority first: ACTION_NDEF_DISCOVERED, ACTION_TECH_DISCOVERED and ACTION_TAG_DISCOVERED. Filter for the first where you can. ACTION_TAG_DISCOVERED is deprecated as of API level 37, with the other two in its place; for the same catch all behaviour, list every technology in the tech-list metadata. Two newer changes break older walkthroughs. From Android 16, a tag whose URI scheme is http or https fires ACTION_VIEW instead. From API level 37, an activity wanting NFC intents needs android.permission.DISPATCH_NFC_MESSAGE if you target above Baklava.

So what happens when they refuse differs by platform. Android has nothing to refuse at install. But from Android 16 the user is notified the first time your app gets an NFC intent and can disallow it, under a switch Google's documentation places at Settings, Apps, Special app access, Launch via NFC. Check NfcAdapter.isTagIntentAllowed before blaming your filter. On iOS there is no persistent allow or deny in the documentation. The person sees the system scan sheet with your message, and cancelling returns readerSessionInvalidationErrorUserCanceled.

Google, NFC basics, Android developer documentation (read 3 October 2026)

Where Apple stops you outright

Two things on iOS are not a matter of effort. NFCTagReaderSession does not support selection of payment related application identifiers; Apple points at NFCPaymentTagReaderSession for the European Union. The other is card emulation. CardSession arrived in iOS 17.4 and needs com.apple.developer.nfc.hce plus com.apple.developer.nfc.hce.iso7816.select-identifier-prefixes. Apple says use of that entitlement is managed by Apple, through an application process, and its documented uses are banking and wallet transactions in the European Economic Area.

Android has no equivalent gatekeeper. Host based card emulation has existed since Android 4.4, through HostApduService, and nobody at Google approves it. Payment identifiers still need the user: under CATEGORY_PAYMENT you transact only as the default payment app, the Wallet role holder on Android 15 and later, or in the foreground through setPreferredService.

Now the expensive part. Apple says CardSession requires the presence of an NFC reader, which is not supported in Simulator, and Core NFC requires a device that supports near field communication. Background tag reading is iPhone XS and later, and only for a URI record that is a universal link or a supported URL scheme. Buy a phone, blank NDEF tags, and a reader if you are emulating a card. If the plan was a credential in Apple Wallet, passes and wallet starts there.

What each platform asks for, job by job

What you want to doiOS asks forAndroid asks forPlatform approvalHardware to test it
Read an NDEF tagNear Field Communication Tag Reading capability, plus NFCReaderUsageDescriptionandroid.permission.NFC, protection level normalNone either sideA phone and a blank NDEF tag
Read ISO 7816, ISO 15693, FeliCa or MIFARESame capability, plus the ISO7816 application identifiers keySame permission, plus a tech-list resource and ACTION_TECH_DISCOVEREDNone either sideA phone and that exact tag type
Read with no app in the foregroundBackground tag reading, iPhone XS and later, universal link or supported schemeTag dispatch, plus DISPATCH_NFC_MESSAGE above BaklavaNone either sideA phone, a tag and a live domain for iOS
Emulate a contactless cardCardSession from iOS 17.4, com.apple.developer.nfc.hce entitlementHostApduService since Android 4.4, BIND_NFC_SERVICE on the serviceApple, by application. Google does not gate itA phone and a real contactless reader
Handle a payment application identifierNot in NFCTagReaderSession. NFCPaymentTagReaderSession in the EUCATEGORY_PAYMENT, default payment app or setPreferredServiceApple, by application. On Android the user picksA phone, a reader and that identifier

Building a tag reader into an app you own

The reading code is small. On iOS you create an NFCNDEFReaderSession, set alertMessage, call begin to start polling, then handle the didDetectNDEFs delegate call. Writing uses the same session with invalidateAfterFirstRead off: connect, query the NDEF status, and write only when it comes back readWrite. On Android you read EXTRA_NDEF_MESSAGES in onNewIntent.

Newly is an AI app builder. You describe an app in plain English and it writes a real React Native and TypeScript project you own, runs it on cloud iOS and Android simulators, and ships to TestFlight and Google Play internal testing, for $25 a month with no free plan. Be clear about the limit. Those cloud simulators cannot read a tag, because no simulator can, and both platform APIs are native. A React Native NFC reader therefore wraps a native module, with the capability on iOS and the manifest entries on Android. The code comes out through the two way GitHub sync in Deploy, or as a ZIP from Settings.

Write the failure path before the happy one. A read only tag. A tag that is not NDEF formatted. Two tags in the field at once, which Apple's sample handles by asking the person to pull them apart and restarting polling. Someone who cancels the sheet. Those are normal, and an app that reports them as errors feels broken on the first tap.

Questions people ask about adding NFC

Yes. Turn on the Near Field Communication Tag Reading capability for the target. That writes the com.apple.developer.nfc.readersession.formats entitlement into your entitlements file and adds the feature to your App ID. You also need an NFCReaderUsageDescription string in Info.plist, and Apple's sample says the app exits if it reads a tag without it. You do not apply to Apple for it.

Decide which gate you are walking through

Write down the one job the app has to do, then enable the capability on iOS and add the manifest line on Android before any reading code. Order a phone and a pack of blank tags in the same hour.

Start building