What is the reliable approach to fetch a consistent and complete list of installed applications?

Is system_profiler the recommended approach for retrieving installed application data on macOS?

If not, what is the preferred and reliable alternative to fetch a consistent and complete list of installed applications?

Answered by brunerd in 885220022

Recommended, preferred and reliable?! That's a tall order! 😅

I can offer a few method, mdfind is super fast, it uses the content type names and values you can get with mdls <app path>

This one gets all application types, including .service files, the kMDItemContentTypeTree has a multiple of types in it

mdfind 'kMDItemContentTypeTree == com.apple.application'

This one doesn't include .service files since it uses the kMDItemContentType which can only have one value:

mdfind 'kMDItemContentType == com.apple.application-bundle'

Lastly (and the most slow), would be system_profiler. This one-liner assumed the Mac is macOS Tahoe which ships with jq:

system_profiler -json SPApplicationsDataType | jq -Mr '.. | .path? // empty'

Oh and this is UI only and doesn't export a list (although there probably is a way) but you can paste this in Script Editor to get a list of apps (that is considerably shorter than the other methods): choose application with prompt "Pick an app:"

Accepted Answer

Recommended, preferred and reliable?! That's a tall order! 😅

I can offer a few method, mdfind is super fast, it uses the content type names and values you can get with mdls <app path>

This one gets all application types, including .service files, the kMDItemContentTypeTree has a multiple of types in it

mdfind 'kMDItemContentTypeTree == com.apple.application'

This one doesn't include .service files since it uses the kMDItemContentType which can only have one value:

mdfind 'kMDItemContentType == com.apple.application-bundle'

Lastly (and the most slow), would be system_profiler. This one-liner assumed the Mac is macOS Tahoe which ships with jq:

system_profiler -json SPApplicationsDataType | jq -Mr '.. | .path? // empty'

Oh and this is UI only and doesn't export a list (although there probably is a way) but you can paste this in Script Editor to get a list of apps (that is considerably shorter than the other methods): choose application with prompt "Pick an app:"

Thanks for the suggestions! mdfind is indeed fast and those content-type queries are elegant.

However, the core constraint we're solving for is Spotlight disabled on managed endpoints. In enterprise environments, some orgs disable Spotlight indexing via MDM policy for security or performance reasons.

When Spotlight is off,

mdfind returns nothing. It queries the Spotlight index, which is empty or stale when indexing is disabled. Same applies to NSMetadataQuery.

system_profiler SPApplicationsDataType also breaks. We tested this empirically and it was unable to return the complete application list with Spotlight disabled. It internally depends on Spotlight metadata for app discovery beyond a minimal hardcoded set.

choose application uses Launch Services under the hood, which is the same data source we're already tapping into, but it's UI-only and not suitable for a background agent.

So we went with _LSCopyAllApplicationURLs — the private Launch Services API backed by the lsd daemon. It works completely independent of Spotlight. We supplement it with a targeted filesystem scan of standard app directories to catch newly installed apps that lsd hasn't registered yet.

The combination gives us Spotlight-equivalent coverage with zero Spotlight dependency, and newly installed apps are detected immediately via the filesystem scan even before lsd picks them up.

mdfind would absolutely be our first choice if we could guarantee Spotlight is always on — it's faster and cleaner. But since we can't control that on customer machines, we needed something that works regardless.

What is the reliable approach to fetch a consistent and complete list of installed applications?
 
 
Q