Skip to content
App Signing & PushPart 18 of 44
App SigningMobile DevelopmentFlutter

Bundle ID vs App ID: The Name in Your App and Apple's Record of It

A bundle ID is the name inside your app. An App ID is Apple's record of it: Team ID plus capabilities. Explicit vs wildcard, extensions, and Android's applicationId.

By Bimal Khatri·13 min read·Sep 17, 2026·Updated Sep 17, 2026
Bundle ID vs App ID: The Name in Your App and Apple's Record of It

A bundle ID is the name you give your app, and it is written inside the app itself: com.example.app. An App ID is Apple's record of that name in your developer account: your Team ID in front of it (A1B2C3D4E5.com.example.app), plus the list of Apple services the app is allowed to use.

So the bundle ID answers "which app is this?", and the App ID answers "which team owns that name, and what may the app do?" You choose the first. Apple stores the second. Xcode usually registers the App ID for you, which is why plenty of developers ship apps for years without noticing there are two.

Below: where each one lives, the two kinds of App ID, how widgets and other extensions fit in, and how Android's applicationId compares.

The two side by side

Bundle IDApp ID
What it isA text name for one appApple's registration of that name
Who creates itYou, in XcodeThe developer portal, or Xcode on your behalf
Where it livesInside the app, as CFBundleIdentifier in Info.plistCertificates, Identifiers & Profiles, under Identifiers
Examplecom.example.appA1B2C3D4E5.com.example.app
What else it carriesNothingThe capabilities the app may use, such as Push Notifications
Can it cover many apps?NoYes, if it is a wildcard
Can it change?Only until the first build is uploadedIts capabilities can change at any time, but an explicit App ID for an uploaded app cannot be deleted

A comparison from everyday life: the bundle ID is the name painted on a shop's sign. The App ID is the shop's entry in the local business register, which records who owns it and which licences it holds. The sign alone proves nothing; an inspector checks the register. The comparison fails in one place. Two shops in different towns can share a name, but Apple requires every bundle ID to be unique.

How the name turns into a signed app

A map with four boxes. The Xcode target holds the bundle ID com.example.app. An arrow labelled registered as leads down to the App ID, A1B2C3D4E5.com.example.app with its capabilities. An arrow labelled named inside leads to the provisioning profile. An arrow labelled used to sign leads up to the signed app, whose application-identifier entitlement is A1B2C3D4E5.com.example.app. A highlighted arrow along the top shows Xcode building and signing the target.

  1. You set the bundle ID on the app target in Xcode. It is stored in the build setting PRODUCT_BUNDLE_IDENTIFIER, and Info.plist picks it up as CFBundleIdentifier.
  2. The App ID registers that bundle ID under your team and records which capabilities are switched on.
  3. A provisioning profile names one App ID, along with the certificates allowed to sign and, for test builds, the devices allowed to run it.
  4. When Xcode signs the app, it writes the full App ID into the signature as the application-identifier entitlement.
  5. When the app runs on a device, the device checks that the profile is genuine and that the app meets its terms.

If the bundle ID in step 1 and the App ID in step 3 disagree, the build will not install. That is the first of the five checks covered in provisioning profiles explained.

The bundle ID in detail

What it may contain

Apple's rules are short:

  • Only letters (A to Z, a to z), digits, hyphens and full stops. No spaces and no underscores.
  • By convention it is written as a reversed domain name: com.yourcompany.appname.
  • It must be unique. Xcode's default is your organisation identifier joined to the product name you typed when creating the project.

Apple's documentation says bundle IDs are case-insensitive. Firebase, on the other hand, treats the bundle ID you register there as case-sensitive. The safe habit is to pick one spelling and copy it exactly everywhere.

Flutter builds its default from the --org option of flutter create, which is com.example unless you pass something else. That default is fine for learning, but choose your own before you register anything with Apple.

Where to find it

  • In Xcode: select the app target. The General tab shows it under Identity as Bundle Identifier, and the Signing & Capabilities tab shows it under Signing.
  • Per build configuration: the target's Build Settings tab, in the Packaging section, under Product Bundle Identifier. Expand the row to see Debug, Release and any others.
  • In a built app: read it straight from the app's Info.plist.
plutil -extract CFBundleIdentifier raw -o - Runner.app/Info.plist
  • For an app already on the App Store: App Store Connect calls the number in an app's App Store web address its Apple ID. Apple's public lookup service takes that number, and its answer includes a bundleId field.
curl -s "https://itunes.apple.com/lookup?id=YOUR_APP_STORE_ID"

Everywhere the bundle ID is remembered

The bundle ID is copied into more places than most people expect, which is why changing it later is so disruptive:

PlaceHow it uses the bundle ID
App Store ConnectThe app record must match the Xcode project, and the bundle ID is fixed once a build is uploaded
App ID and profilesThe App ID registers it; every profile for the app names that App ID
Push notificationsThe APNs topic is normally the bundle ID
FirebaseEach Apple app in a Firebase project is registered by bundle ID, which cannot be edited afterwards
KeychainThe app's private keychain group is the Team ID plus the bundle ID
Universal linksThe apple-app-site-association file on your website lists the Team ID and bundle ID

What the App ID adds

An App ID is what Apple calls "a two-part string": a prefix and a bundle ID.

The prefix is your Team ID for any account opened since mid-2011. Apple's older technote on the subject explains that accounts from before then may also have older-style ten-character prefixes. Either way, the prefix is what groups your apps so they can share keychain data.

The capabilities are an allow list. Push Notifications, Sign in with Apple, App Groups, iCloud, Apple Pay and the rest are switched on per App ID. An app can only use the ones switched on here. In-App Purchase is on by default for an explicit App ID. Some capabilities are managed: Apple has to approve your team first, and you ask from the App ID's Capability Requests tab.

One App ID can cover every platform. Since Xcode 11.4, a single App ID can build the iOS, macOS, tvOS and watchOS versions of the same app.

Xcode makes its own. With automatic signing, Xcode registers App IDs for you. Their names in the portal begin with XC, and there is one called "XC Wildcard".

Changing an App ID's capabilities invalidates every provisioning profile that contains it, so profiles must be regenerated afterwards. Xcode does that for you with automatic signing; with manual signing it is your job.

You can see the full App ID inside any provisioning profile, after unwrapping it (the provisioning profile post explains the first command):

security cms -D -i profile.mobileprovision -o profile.plist
plutil -extract Entitlements.application-identifier raw -o - profile.plist

It prints the prefix and the bundle ID joined together:

A1B2C3D4E5.com.example.app

Explicit and wildcard App IDs

A comparison chart of explicit and wildcard App IDs. An explicit App ID is written A1B2C3D4E5.com.example.app and matches exactly one bundle ID; Push Notifications and other capabilities that need an explicit App ID are available. A wildcard App ID is written A1B2C3D4E5.com.example.* and matches every bundle ID starting with com.example.; push cannot be configured and the other checkboxes are disabled. Explicit is for every app you ship; wildcard suits quick test apps.

When you register an App ID you pick one of two types:

  • An explicit App ID names exactly one bundle ID.
  • A wildcard App ID ends in an asterisk and matches every bundle ID that starts with what comes before it. In the portal you type only the part before the asterisk.

The portal disables any capability checkbox that needs an explicit App ID while you are creating a wildcard one. Push Notifications is the one most people run into: it cannot be configured on a wildcard. Apple's managed-capability notes add that many capabilities and entitlements require an explicit App ID.

Apple's own pages are not perfectly consistent about shipping with a wildcard. The help page on App Store profiles says an upload needs an app record registered with an explicit App ID, yet the same page lists Xcode's "XC Wildcard" as a valid choice when it is the only one offered. And when an app is transferred to another team, Apple converts a wildcard App ID into an explicit one. The practical rule is simple: give every app you intend to ship its own explicit App ID from the start.

Extensions, widgets and App Clips

A tree with the main app, com.example.app, at the top and three children: a widget extension with bundle ID com.example.app.widget, a notification service extension with com.example.app.NotificationService, and an App Clip with com.example.app.Clip. Each child has its own App ID and profile.

An app extension is a separate bundle inside your app, so it has its own bundle ID. That ID must start with the main app's bundle ID, and the extension needs its own App ID and its own provisioning profile.

  • Widgets and notification extensions add a suffix of your choice: com.example.app.widget.
  • App Clips follow the same pattern. When you register one, the portal appends a product name to the parent's App ID, and Xcode's default for that name is Clip.
  • Watch apps built in the same project as their iOS app use fixed suffixes: .watchkitapp for the WatchKit app and .watchkitextension for its extension.

Each of these App IDs has its own capabilities. If the widget needs to read the main app's data, both App IDs need the same App Group, which App Groups on iOS covers step by step.

Android's applicationId, and what it is not

Android has one direct equivalent and one near-miss.

iOS bundle IDAndroid applicationIdAndroid namespace
What it identifiesThe app, on the device and in the App StoreThe app, on the device and in Google PlayThe Kotlin or Java package of the generated R and BuildConfig classes
Where you set itXcode target, PRODUCT_BUNDLE_IDENTIFIERdefaultConfig in the app module's Gradle fileThe android block of the same file
Allowed charactersLetters, digits, hyphens, full stopsLetters, digits, underscores; at least two segments, each starting with a letterA normal package name
Change after release?No, once a build is uploadedNo. Google Play treats a new one as a different appYes, if applicationId is set explicitly
VariantsA different bundle ID per build configurationapplicationIdSuffix per build type or flavourStays the same

The namespace is where people get caught. It used to be the same thing as the app's identity, and Android's documentation still recommends keeping the two equal. But they are separate settings, and if applicationId is missing, it silently takes the namespace's value. Renaming the namespace would then rename the app. Setting both explicitly avoids that:

android {
    namespace = "com.example.app"

    defaultConfig {
        applicationId = "com.example.app"
    }

    buildTypes {
        getByName("debug") {
            // Lets a debug build sit next to the release build on one phone.
            applicationIdSuffix = ".debug"
        }
    }
}

Look closely at the character rules in the table. A hyphen is legal in a bundle ID but not in an applicationId, and an underscore is the reverse. Flutter handles this for you: a project created as my_app gets com.example.myApp on iOS and com.example.my_app on Android. The two IDs do not have to match; they are independent settings that often happen to hold the same string.

To see an Android app's applicationId from outside, look at its Play Store address. The id= value in play.google.com/store/apps/details?id=... is the package name.

Common mistakes

  • Treating the bundle ID as the app's name. People see the display name on the Home screen (CFBundleDisplayName) and the name set in App Store Connect. Both can change later; the bundle ID cannot once a build is uploaded.
  • Keeping com.example into production. It is a placeholder. Choose a name based on a domain you control before registering anything.
  • Turning on a capability in Xcode but not on the App ID. With manual signing, the App ID and the profile must both allow it, or the build fails.
  • Expecting push to work with a wildcard App ID. It cannot be configured there. Register an explicit App ID.
  • Giving an extension an unrelated bundle ID. It must start with the main app's bundle ID.
  • Spelling the bundle ID differently in Xcode and Firebase. Firebase compares it exactly, and you cannot edit it there afterwards.
  • Changing the Android namespace without an explicit applicationId. The app's identity changes with it, and Google Play sees a new app.
  • Changing the bundle ID after the first upload. Apple does not allow it. See changing a bundle ID for what you can do instead.

Questions people ask

Is a bundle ID the same as an App ID?

No. The bundle ID is the name inside your app. The App ID is Apple's registration of that name, with your Team ID in front and a list of allowed capabilities attached.

Where do I find the bundle ID in Xcode?

Select your app target and open the General tab: it is the Bundle Identifier field under Identity. In a Flutter project, open ios/Runner.xcworkspace and select the Runner target.

What is the App ID prefix?

The part before the first full stop in an App ID. For accounts created since mid-2011 it is the Team ID, a ten-character code shown in your membership details.

Is a bundle ID case-sensitive?

Apple documents bundle IDs as case-insensitive, but other systems, Firebase among them, compare them exactly. Use one spelling everywhere.

Should the iOS bundle ID and the Android package name be the same?

They can be, and many teams keep them equal for tidiness, but nothing requires it. Their character rules differ, so a name with a hyphen or an underscore cannot be used on both.

What is the XC Wildcard App ID?

A wildcard App ID that Xcode creates and manages for automatic signing. Like any wildcard, it cannot carry capabilities such as push. Xcode also registers explicit App IDs whose names begin with XC and contain your bundle ID.

Does a widget need its own App ID?

Yes. A widget is an extension with its own bundle ID, which starts with the main app's, and it needs its own App ID and provisioning profile. Automatic signing creates them for you.

Can I change my bundle ID?

Only before the first build is uploaded to App Store Connect. After that it is fixed, and a different bundle ID means a different app. The details are in changing a bundle ID.

Where this comes from

Checked against the platform owners' documentation in September 2026:

Keep reading

More writing

Keep reading