Skip to main content

Info.plist Usage Descriptions: Permission Strings and Examples

Info.plist usage descriptions like NSCameraUsageDescription must exist before you access protected data, or the app crashes and uploads get ITMS-90683.

Info.plist usage descriptions are String keys such as NSCameraUsageDescription that you must add before your app accesses the camera, photos, location or contacts. The system shows that sentence in the permission alert, so write one specific line about what the data is for, like “Used to scan the QR code on your parcel and fill in the tracking number.” Without the key, the app crashes or the request fails as soon as it tries, and uploading to App Store Connect gets you ITMS-90683.

This article lists the key for each permission, when you need it and sample wording you can adapt, then covers localization and how to add the keys in KXBuild. Key names follow Apple’s Protected resources documentation, and everything below is as of October 2026.

What should you know before writing usage descriptions?

  • Keys and values. Each permission has a String key, such as NSCameraUsageDescription, and the value is the sentence the user sees. The system generates the alert title, which already includes the app name, so leave the app name out of your text.
  • Add only what you use. Add keys only for features the app really uses. Extra keys make App Review ask why you need them, and missing ones cause problems at access time.
  • Explain the purpose. Guideline 5.1.1(ii) requires purpose strings to clearly and completely describe how you use the data. The hard requirements in Apple’s Requesting access to protected resources are that the string isn’t empty or only whitespace, is shorter than 4,000 bytes, has the right type (usually a string), and is accurate and specific, in every localized language too.

Which Info.plist key does each permission need?

The wording in the table is only an example. Rewrite it to match what your app actually does, saying what the data is used for and what the user gets.

Permission Info.plist key When you need it Sample purpose string
Camera NSCameraUsageDescription Taking photos, recording video, scanning codes Scan the QR code on your package to fill in the tracking number automatically.
Microphone NSMicrophoneUsageDescription Recording audio, voice messages, video with sound Record voice messages to send to your contacts.
Photos (read) NSPhotoLibraryUsageDescription Reading photos and videos from the library Choose a photo from your library as your profile picture.
Photos (add only) NSPhotoLibraryAddUsageDescription Saving to the library without reading it Save the posters you edit to your photo library.
Location (when in use) NSLocationWhenInUseUsageDescription Location in the foreground, also required when requesting Always Show stores near you and how far away they are.
Location (always) NSLocationAlwaysAndWhenInUseUsageDescription Location in the background too Record your running route in the background, even when the screen is locked.
Contacts NSContactsUsageDescription Reading or writing contacts Pick a contact to send money to quickly.
Calendar (full access) NSCalendarsFullAccessUsageDescription iOS 17 and later, reading and changing calendars Read your schedule to book meetings in your free time.
Calendar (write only) NSCalendarsWriteOnlyAccessUsageDescription iOS 17 and later, adding events only Add the classes you book to your calendar.
Reminders NSRemindersFullAccessUsageDescription iOS 17 and later, reading and writing reminders Sync your to-dos to Reminders so you’re reminded on time.
Bluetooth NSBluetoothAlwaysUsageDescription Connecting to devices over Bluetooth Connect to your smart scale and sync your measurements.
Local network NSLocalNetworkUsageDescription Finding or connecting to devices on the local network, using Bonjour Find printers on the same Wi-Fi network.
Face ID NSFaceIDUsageDescription Authenticating with Face ID Sign in quickly with Face ID instead of typing your password.
Motion & Fitness NSMotionUsageDescription Reading step counts, activity type and other motion data Count your daily steps and build a weekly activity report.
Speech recognition NSSpeechRecognitionUsageDescription Converting speech to text Turn what you say into text for quick notes.
Health (read) NSHealthShareUsageDescription Reading data from Health Read sleep data from Health to analyze your sleep schedule.
Health (write) NSHealthUpdateUsageDescription Writing data to Health Save the water intake you log to Health.
Tracking (ATT) NSUserTrackingUsageDescription Tracking users across apps or websites, reading the advertising identifier Show you more relevant ads. You can turn this off in Settings at any time.
Media library NSAppleMusicUsageDescription Accessing the music library and Apple Music data Use songs from your library as background music for videos.
HomeKit NSHomeKitUsageDescription Reading and controlling home accessories Find the lights and outlets in your home so you can switch them from the app.
NFC NFCReaderUsageDescription Reading NFC tags Read the balance on your transit card.

A few cases trip people up, so they get their own sections.

The two location keys

According to Core Location’s authorization documentation, NSLocationWhenInUseUsageDescription is required for both When In Use and Always requests, and NSLocationAlwaysAndWhenInUseUsageDescription is only needed in addition when you request Always. An app that needs background location must have both keys, and the Always key alone isn’t enough. If a key is missing, the authorization request fails immediately without showing an alert.

Write the two sentences separately. The When In Use string describes the foreground feature, and the Always string explains why you need location after the screen locks. If you don’t need background location, don’t add the Always key, because App Review will ask you to justify background use.

New calendar and reminders keys

iOS 17 split calendar access into full access and write-only access, and Reminders now uses NSRemindersFullAccessUsageDescription. According to EventKit’s documentation, on iOS 17 and later, if you only have the old NSCalendarsUsageDescription key, the system automatically denies access requests and no alert appears.

  • If you only add events to the calendar, use write-only access instead of requesting full access.
  • If your minimum deployment target is iOS 16 or earlier, also add the old NSCalendarsUsageDescription and NSRemindersUsageDescription keys. Older systems use them.
  • If you only present the system event editor and let the user save the event, you don’t need calendar permission on iOS 17 and later.

Reading photos vs. adding only

If you only save images to the library without reading it, use NSPhotoLibraryAddUsageDescription. To let users pick images, the system photo picker (PHPicker or SwiftUI’s PhotosPicker) needs no photo library permission. You only need NSPhotoLibraryUsageDescription when you read the whole library directly.

Older keys for low deployment targets

  • If you support versions earlier than iOS 13 and use Bluetooth, add both NSBluetoothAlwaysUsageDescription and NSBluetoothPeripheralUsageDescription.
  • If you support versions earlier than iOS 11 and use background location, also add NSLocationAlwaysUsageDescription, with the same wording as the Always string.

Permissions that also need a capability

For Health, HomeKit and NFC, a purpose string isn’t enough. You also have to enable the matching capability for the App ID, add the matching entry to the project’s .entitlements file and regenerate the provisioning profile. If you use Bonjour on the local network, also list the service types, such as _ipp._tcp, in the NSBonjourServices array. See Certificates and signing for these settings.

How should you word permission strings?

App Review checks whether the sentence explains the purpose. Here are some comparisons.

Avoid Prefer
This app needs access to your camera. Scan the QR code on your package to fill in the tracking number automatically.
The app needs location permission to work properly. Show stores near you and how far away they are.
For a better user experience. Choose a photo from your library as your profile picture.
Please allow access, or the app won’t work. Record voice messages to send to your contacts.

Keep these points in mind.

  • Describe the specific feature in one sentence, matching the action in the app that triggers the request.
  • If one permission serves several features, name the main one or two instead of listing them all.
  • Don’t pressure users with lines like “or the app won’t work”. If a user declines, the rest of the app should keep working.
  • Write in the same language as the app’s UI. An app with a single UI language uses that language, and a multilingual app localizes the strings as described in the next section.

For common permission-related rejections, see 12 common App Store rejection reasons.

How do you localize usage descriptions?

Write the development-language sentence in Info.plist and translate the other languages in a localization file, using the Info.plist key name as the key. The key itself must stay in Info.plist. Putting it only in the localization file doesn’t count.

New projects use a string catalog. The file must be named exactly InfoPlist.xcstrings, live in the app’s source folder and be added to the target. After one build, the purpose strings you use appear in the table, and you fill in the translations row by row.

 1{
 2  "sourceLanguage" : "en",
 3  "strings" : {
 4    "NSCameraUsageDescription" : {
 5      "localizations" : {
 6        "es" : {
 7          "stringUnit" : { "state" : "translated", "value" : "Escanea el código QR de tu paquete para rellenar automáticamente el número de seguimiento." }
 8        }
 9      }
10    }
11  },
12  "version" : "1.0"
13}

Older projects that already use InfoPlist.strings add a line to xx.lproj/InfoPlist.strings for each language, with double quotes on both sides of the equals sign and a semicolon at the end.

1/* es.lproj/InfoPlist.strings */
2"NSCameraUsageDescription" = "Escanea el código QR de tu paquete para rellenar automáticamente el número de seguimiento.";
3"NSLocationWhenInUseUsageDescription" = "Muestra las tiendas cercanas y a qué distancia están.";

In KXBuild, double-clicking a .xcstrings file or a .strings file in an .lproj folder opens the KXBuild Localization Editor, with every language side by side. For how to create InfoPlist.xcstrings and add it to the target, see iOS app icon sizes, launch screen and localization done right.

What happens when a key is missing?

Situation Symptom Fix
Accessing a protected resource at runtime Access fails. For most permissions the app crashes immediately, and the debug console output names the missing key Add the key named in the output
Missing location key The authorization request fails immediately with no alert Add at least NSLocationWhenInUseUsageDescription
Only the old calendar key on iOS 17 The system denies access automatically with no alert Add the new full access or write-only key
Uploading to App Store Connect You get ITMS-90683: Missing purpose string in Info.plist, and the email names the missing key Add the key, increase the build number and upload again

ITMS-90683 is triggered when your code references an API that accesses sensitive data, or has the matching entitlement, whether or not you actually call it. If a third-party SDK includes camera or location code, you get the email even if you don’t use that feature. Add the key anyway with wording that matches what the SDK actually does, or drop the SDK module you don’t need. For other upload error codes, see App Store upload ITMS errors.

How do you add the keys in KXBuild?

When you use KXBuild on Windows, Linux or macOS, first check whether the target has an Info.plist file. Right-click the target and choose KXBuild: Edit Target Settings. If Info.plist File on the General page has a path, you’re in the first case below. If it’s empty and Generate Info.plist File is on, you’re in the second.

The project has an Info.plist file

  1. Double-click Info.plist in the Explorer to open it in the Property List Editor.
  2. Right-click any row and choose Add Row. Enter NSCameraUsageDescription as the key, choose String as the type and enter your text as the value.
  3. Press Ctrl+S to save. The file keeps its original format. Keep plists in source control as XML so diffs stay readable.

To edit the text directly, right-click and choose KXBuild: Open plist as Text, then add these two lines.

1<key>NSCameraUsageDescription</key>
2<string>Scan the QR code on your package to fill in the tracking number automatically.</string>

Info.plist is generated

These projects store purpose strings as build settings starting with INFOPLIST_KEY_, which the build writes into the app’s Info.plist. Use either method.

  • VS Code extension. In the Project Settings Editor, switch to the Build Settings page, right-click a value cell and choose Add User-Defined Setting. Enter INFOPLIST_KEY_NSCameraUsageDescription as the name and your text as the value, then press Ctrl+S.
  • Command line. Run the command below in the project folder.
1kxbuild project add-setting -k INFOPLIST_KEY_NSCameraUsageDescription -v "Scan the QR code on your package to fill in the tracking number automatically." -t MyApp -P .\MyApp.xcodeproj

For array values such as NSBonjourServices, and for keys that don’t show up in Info.plist after a build, create an Info.plist file with them and enter its path in Info.plist File on the General page. The generated values are merged with this file.

Check after building

After the build finishes, find MyApp.app under ~\DerivedData\<project name>-<hash>\Build\Products\Debug-iphoneos\ and double-click the Info.plist inside it. Check in the Property List Editor that every key is there with the right text. Then press F5 to install on your phone and try every feature that triggers a permission request to see the alert text. A permission you’ve already answered won’t ask again, so delete and reinstall the app before testing again.

Flutter, React Native and Expo

  • Flutter. Add the keys to ios/Runner/Info.plist. Each plugin’s documentation lists the keys it needs.
  • React Native. Add the keys to ios/<project name>/Info.plist.
  • Expo. Add them under expo.ios.infoPlist in app.json, and they’re written into Info.plist when the ios folder is generated. Edits made directly in the ios folder are overwritten the next time it’s generated.

Whatever the project type, the Info.plist inside the built .app is what counts. Open it as described above, confirm every Info.plist usage description is there and matches what the feature really does, then submit for review.

FAQ

What language should Info.plist purpose strings be in?

Use the same language as the app’s UI. Users understand the alert better, and App Review is less likely to find the explanation unclear. A multilingual app translates each string in InfoPlist.xcstrings or InfoPlist.strings.

Why did I get ITMS-90683 when my app doesn’t use the camera?

ITMS-90683 checks whether the code references the related API, and camera or location code inside a third-party SDK counts. Add the key named in the email with wording that describes what that SDK feature really does, or remove the SDK module you don’t need.

Which key do I need for location?

For foreground location only, add just NSLocationWhenInUseUsageDescription. If you need background location, also add NSLocationAlwaysAndWhenInUseUsageDescription, so the app has both.

Why doesn’t the calendar permission alert appear on iOS 17?

On iOS 17 and later, if you only have the old NSCalendarsUsageDescription key, the system denies access automatically. Add NSCalendarsFullAccessUsageDescription or NSCalendarsWriteOnlyAccessUsageDescription as needed, and switch to the iOS 17 authorization APIs.

How should I word a purpose string so App Review accepts it?

State what the data is used for in one sentence that matches the feature that triggers the request, for example “Scan the QR code on your package to fill in the tracking number automatically.” Strings that only repeat the permission name, like “This app needs access to your camera”, often get sent back for changes. Apple makes the final review decision.