Skip to content

Instantly share code, notes, and snippets.

@omundy
Forked from jleaney/how-to-notarize-unity-for-macos.md
Last active October 19, 2025 22:11
Show Gist options
  • Save omundy/b2aa6c5586919b8bda068a7285849725 to your computer and use it in GitHub Desktop.
Save omundy/b2aa6c5586919b8bda068a7285849725 to your computer and use it in GitHub Desktop.
How to notarize a Unity build for MacOs 10.15 Catalina

Build, sign, and notarize a Unity game for macOS

Overview

  1. Prerequisites
  2. Build to macOS from Unity
  3. Create certificates and entitlements
  4. Codesign and upload a macOS app for the App Store
  5. Notarize an app for other platforms
  6. Common Error Messages

Prerequisites

Build to macOS from Unity

  1. Build Settings
    1. Set target platform to Mac OS
    2. DO NOT select Create an Xcode project. Instead, build a single executable, code sign and upload yourself using SignGame.sh (and instructions below)
  2. Player Settings
    1. Set a unique Bundle Identifier (e.g. com.YourCompany.YourGame)
    2. DO NOT check "App Store Validation" (requires players enter their Apple password).

Create certificates and entitlements

1. Create certificates

Certificates for code signing and/or packaging the build.

  1. In your Apple Developer account, view Certificates, Identifiers & Profiles and click + (add)
  2. Choose "Create a New Certificate", select add a "Developer ID Application" certificate.
  3. After clicking continue, follow instructions to create and upload a "Certificate Signing Request" using the Keychain Access app
  4. After you've uploaded the Certificate Signing Request file, you should then be able to download the Developer Id Application certificate.
  5. Once downloaded, click on the file to add it to Keychain Access where you'll see it under the certificates section. It will be called something like "Developer ID Applicate : YourCompanyName (0123456789)". Make sure to save a backup copy of your private and public keys somewhere secure.
  6. Repeat these steps for "Developer ID Application" and "Mac Installer Distribution"
certs

Once you complete this step you should have a certificate in Keychain Access on your Mac, and you'll be able to see it saved in your Apple account here: https://developer.apple.com/account/resources/certificates/list

2. Create entitlements file

An xml file used to give executable permissions to the app when code signing. Here are the minimum entitlements needed for a Unity build:

  1. Save the below as basic.entitlements in the same folder where you place your Unity build.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
	       <key>com.apple.security.app-sandbox</key>
	       <true/>
	       <key>com.apple.security.cs.disable-library-validation</key>
	       <true/>
	       <key>com.apple.security.cs.disable-executable-page-protection</key>
	       <true/>
    </dict>
</plist>

Codesign and upload a macOS app for the App Store

These steps are covered automatically in CodeSign.sh

1. Change file permissions

For the code signing to work in a later step, we need to change permissions for files within the app directory.

chmod -R a+xr "YourGame.app"

2. Code sign the app

Next, in the command line, use the codesign tool on the permission changed file by using your Developer ID Application certificate (literally the name of the certificate in double quotes).

codesign --deep --force --verify --verbose --timestamp --options runtime --entitlements "$ENTITLEMENTS_FILE" --sign "$CODESIGN_CERT_NAME" "$APP_LOCATION"

If successful, you should see a message similar to:

YourGame.app: signed app bundle with Mach-O universal (x86_64 arm64) [com.YourCompany.YourGame]

3. Package the app

To upload to the App Store you need to create a .pkg file and use a Mac Installer Distribution certificate too

Generate PKG

productbuild --component "$APP_LOCATION" /Applications --sign "$INSTALLER_CERT_NAME" "$PKG_LOCATION"

4. Upload

I recommend installing Apple Transporter. Just drag the app in to upload to the app store

Automated upload option
xcrun altool --upload-app -f YourGame.pkg -t macos -u "YOUR_APPLE_ID" --password "APP_SPECIFIC_PASSWORD"         

You will see something like this if successful:

UPLOAD SUCCEEDED with 0 warnings, 0 messages

Notarize an app for other platforms

Additional steps for other platforms...

  • As of January 2020, all apps running on >= macOS 10.15 Catalina are required to be notarized.
  • For Unity games distributed outside the Mac App Store, such as with Steam, itch.io, etc. the notarization process is done post build using a series of Xcode command line tools.
  • The following steps assume your build and entitlements file are in the same directory.

1. Create an App-Specific Password

Use an app-specific password to sign in to an app or service not provided by Apple. Required to upload a build to Apple servers, the password will look like abcd-efgh-ijkl-mnop

  1. Login to your Apple account
  2. In "Sign-in and Security", click on "App-Specific Passwords"
  3. Click + and create one. Name it something relevant
  4. Store it somewhere secure.

2. Create a zip

Once the code is signed, we need to compress the application into a zip file for uploading. You can do this in the command line.

ditto -c -k --sequesterRsrc --keepParent "YourGame.app" "YourGame.zip"

3. Upload the zip to Apple's notarization service

Now that we have the compressed zip file, upload it to the Apple servers for notarization using the xcrun altool in the command line. In order to do this, you'll need

  • your game's bundle id (defined in Unity Player Settings), something like com.YourCompany.YourGame
  • your Apple ID username (usually an email address)
  • your Apple ID generated password (the one with the format abcd-efgh-ijkl-mnop)
  • your Apple Developer "Provider Short Name". Often this is your Team ID (ten digit alphanumeric id), you can find in the membership section of your Apple developer account
Note If your "Provider Short Name" is not the same as your Team ID, you can find it by running: ``` xcrun iTMSTransporter -m provider -u YourAppleIDUsername -p abcd-efgh-ijkl-mnop ```

4. Authenticate with Apple

First, sign in with your Apple ID (your email address):

xcrun notarytool store-credentials "my-profile" --apple-id "your-apple-id" --team-id "your-team-id"

You'll be prompted to enter your Apple ID password and an app-specific password (i.e. generated password).

OUTPUT You will see something like this if successful:
This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name.

App-specific password for your-apple-id: 
Validating your credentials...
Success. Credentials validated.
Credentials saved to Keychain.
To use them, specify `--keychain-profile "my-profile"`

5. Submit the File

Run the following command, replacing YourGame.zip with the file you want to notarize to upload the build to the notarization service:

  • --keychain-profile "my-profile" refers to the stored credentials
  • --wait ensures the command waits for the notarization process to complete before returning.
  • Note that xcrun altool --notarize-app is no longer functional...
xcrun notarytool submit YourGame.zip --keychain-profile "my-profile" --wait
OUTPUT

Wait for the notarization service to process the upload. This can take anywhere from 1 minute to an hour or sometimes longer if the service is overloaded. If the upload was successful, you should see a message with a RequestUUID similar to:

Conducting pre-submission checks for YourGame.zip and initiating connection to the Apple notary service...
Submission ID received
  id: abcdefgh-1234-5678-90ij-klmnopqrstuv
Upload progress: 100.00% (75.7 MB of 75.7 MB)   
Successfully uploaded file
  id: abcdefgh-1234-5678-90ij-klmnopqrstuv
  path: /Users/.../Unity/_Builds/.../YourGame.zip
Waiting for processing to complete.
Current status: Accepted..........
Processing complete
  id: abcdefgh-1234-5678-90ij-klmnopqrstuv
  status: Accepted

Alternatively, you can ping the service for the current status of the upload using that RequestUUID:

xcrun notarytool log "<RequestUUID>" --keychain-profile "my-profile"

6. Staple the notarization to the app

Once notarized, Apple creates a ticket that you need to "staple" to the app. Attach the ticket to your app:

xcrun stapler staple YourGame.app
OUTPUT You will see something like this if successful:
Processing: /Users/.../Unity/_Builds/.../YourGame.zip
The staple and validate action worked!

7. Verify notarization

After everything is completed we can use the spctl tool to check if the app is recognized as having the proper notarization.

spctl --assess --verbose=4 YourGame.app
OUTPUT If successful, you should see a message similar to:
YourGame.app: accepted
source=Notarized Developer ID

8. Upload and download to verify

Whether or not the notarization was successful, if you try and open the app on your local machine, everything will appear to work fine. A good way to double check everything is actually working is to upload the notarized build to somewhere on the web (e.g. Itch.io, or even Google Drive), download it, and then see if the app opens properly. If working correctly, then all you should see is a small warning that you downloaded it from the web and then it should open normally.

Common Error Messages

  1. You cannot upload an .app to the App Store. Convert to a .pkg first (see above)
xcrun altool --upload-app -f YourGame.app -t macos -u "email" --password "1234-1234-1234-1234" 

> Error uploading 'YourGame.app'.
> [altool.6000026BC1C0] Unable to upload archive. Failed to get authorization for username 'username' and password.
  1. Make sure you have the right entitlements enabled (see above)
xcrun altool --upload-app -f YourGame.pkg -t macos -u "email" --password "1234-1234-1234-1234"       

> Running altool at path '/Applications/Xcode.app/Contents/SharedFrameworks/ContentDeliveryServices.framework/Frameworks/AppStoreService.framework/Support/altool'...
> 2025-10-09 12:34:28.877 ERROR: [altool.600003E141C0] [ContentDelivery.Uploader.600003E141C0] Validation failed (409) App sandbox not enabled. The following executables must include the "com.apple.security.app-sandbox" entitlement ...
  1. You used the wrong certificates
90238: Invalid signature. The executable, at the YourGame.app/Contents/PlugIns/lib_burst_generated.bundle” path, has the following signing error(s): [valid on disk. lib_burst_generated.bundle: satisfies its Designated Requirement. test-requirement: code failed to satisfy specified code requirement(s)]. For details about signing Mac code for distribution, visit: https://developer.apple.com/documentation/xcode/creating-distribution-signed-code-for-the-mac.
  1. Missing provisioning profile
Error message: ITMS-90889: Cannot be used with TestFlight because the bundle "YourGame.app" is missing a provisioning profile. Main bundles are expected to have provisioning profiles in order to be eligible for TestFlight.

Ref Do I need a Mac Provisioning Profile (Distribution) when uploading my unity app to the Mac App Store?

References

#!/bin/bash
# Instructions
# https://gist.github.com/omundy/b2aa6c5586919b8bda068a7285849725
APPLE_ID="[email protected]"
TEAM_ID="12345ABCDE"
# APP STORE (paste in your certificate names from Keychain Access between the double quotes).
APPLE_CODESIGN_CERT_NAME="3rd Party Mac Developer Application: Company Name (12345ABCDE)"
APPLE_INSTALLER_CERT_NAME="3rd Party Mac Developer Installer: Company Name (12345ABCDE)"
# for notarization
DEV_ID_CODESIGN_CERT_NAME="Developer ID Application: Company Name (12345ABCDE)"
DEV_ID_INSTALLER_CERT_NAME="Developer ID Installer: Company Name (12345ABCDE)"
ENTITLEMENTS_FILE="basic.entitlements" # app permissions
APP_LOCATION="YourGame.app" # your original build
PKG_LOCATION="YourGame.pkg" # pkg exported to send to app store
ZIP_NOTARIZE_LOCATION="YourGame-NotaryOnly.zip" # zipped build for notarization (can be deleted after zipped build created)
ZIP_LOCATION="YourGame.zip" # zipped (and notarized) build
# Create Provisioning Profile at link below > Distribution > Mac App Store Connect
# https://developer.apple.com/account/resources/profiles/list
PROV_PROFILE="/Users/username/.../ProvisioningProfile.provisionprofile"
APP_SPECIFIC_PASSWORD="1234-abcd-5678-efgh"
#############################################################################################################
echo ""
echo "βœ… 1-START
"
echo "πŸ‘‰ Grant execution permission ..."
chmod -R a+xr "$APP_LOCATION"
# NOTE: NEVER COULD FIGURE THIS OUT. ALWAYS UPLOADED WITH WARNING. OH WELL.
# echo "πŸ‘‰ Copy (and rename) provisioning profile (to work with TestFlight) ..."
# # https://developer.apple.com/documentation/bundleresources/placing-content-in-a-bundle
# # (2025) Provisioning Profiles for macOS Apps https://blog.xojo.com/2025/01/30/provisioning-profiles-for-macos-apps/
# cp $PROV_PROFILE $APP_LOCATION/Contents/embedded.provisionprofile
echo "
βœ…βœ… 2-START SIGNING
"
read -p "Do you want to sign & package the app for the Mac App Store? (y) or for sideloading (Itch.io, etc.)? (n) " target
if [ "$target" == "y" ]; then
CODESIGN_CERT_NAME="$APPLE_CODESIGN_CERT_NAME" # app store
INSTALLER_CERT_NAME="$APPLE_INSTALLER_CERT_NAME"
else
CODESIGN_CERT_NAME="$DEV_ID_CODESIGN_CERT_NAME" # sideloading
# INSTALLER_CERT_NAME="$DEV_ID_INSTALLER_CERT_NAME" # no package required for Itch.io - just the app
fi
echo ""
echo "πŸ‘‰ Code sign the app ..."
# reference https://docs.unity3d.com/Manual/macoscodesigning.html
# "Change Developer ID Application to 3rd Party Mac Developer Application if you’re deploying to the Mac App Store" https://medium.com/@yoonicode/building-unity-apps-to-macos-the-ultimate-guide-6d13ca2d84d0
codesign --deep --force --verify --verbose --timestamp --options runtime --entitlements "$ENTITLEMENTS_FILE" --sign "$CODESIGN_CERT_NAME" "$APP_LOCATION"
echo ""
echo "πŸ‘‰ Confirm code signing ..."
codesign -vvv --deep "$APP_LOCATION"
echo ""
echo "πŸ‘‰ OPTIONAL COMMANDS YOU CAN USE TO DEBUG THE .APP ..."
echo "codesign --verify --verbose=4 $APP_LOCATION"
echo "codesign --display --verbose=4 --entitlements - $APP_LOCATION"
echo "codesign --display --verbose=4 --requirements - $APP_LOCATION"
if [ "$target" == "y" ]; then
echo "
βœ…βœ…βœ… 3-SIGNED - START PACKAGING
"
echo "πŸ‘‰ Generating pkg ..."
productbuild --component "$APP_LOCATION" /Applications --sign "$INSTALLER_CERT_NAME" "$PKG_LOCATION"
echo ""
echo "πŸ‘‰ Open Apple Transporter and drag the app in to upload to the app store ..."
echo "https://apps.apple.com/us/app/transporter/id1450874784?mt=12"
# NOTE: ^ Apple Transporter is easy, free, and provided better feedback
# echo "Auto Upload option..."
# if [ "$target" == "y" ]; then
# read -n1 -p "Do you want to upload to App Store now? (y/n) " choice
# echo ""
# if [ "$choice" == "y" ]; then
# echo "Uploading to app store..."
# xcrun altool --upload-app --file "$PKG_LOCATION" --type macos --username "$APPLE_ID" --password "$APP_SPECIFIC_PASSWORD"
# fi
# fi
return
fi
echo "
βœ…βœ…βœ… SIGNED - START NOTARIZATION (for Itch.io, etc)
"
echo "πŸ‘‰ Compress app into a Zip for notarization ..."
# Notarize with Xcode and command-line tools https://docs.unity3d.com/Manual/macosnotarizationxcode.html
ditto -c -k --sequesterRsrc --keepParent "$APP_LOCATION" "$ZIP_NOTARIZE_LOCATION"
echo ""
echo "πŸ‘‰ Sign into Apple's notarization service ..."
xcrun notarytool store-credentials "my-profile" --apple-id "$APPLE_ID" --team-id "$TEAM_ID"
# echo ""
# echo "πŸ‘‰ OPTIONAL Get provider_short_name ..."
# xcrun iTMSTransporter -m provider -u "$APPLE_ID" -p "$APP_SPECIFIC_PASSWORD"
echo ""
echo "πŸ‘‰ Submit the zip to Apple's notarization service ..."
xcrun notarytool submit "$ZIP_NOTARIZE_LOCATION" --keychain-profile "my-profile" --wait
echo ""
echo "πŸ‘‰ Staple the notarization ticket to app ..."
xcrun stapler staple "$APP_LOCATION"
# echo ""
# echo "πŸ‘‰ OPTIONAL if the above fails, run this"
# xcrun notarytool log <submission-id> --keychain-profile "my-profile"
echo ""
echo "πŸ‘‰ Verify notarization ..."
spctl --assess --verbose=4 "$APP_LOCATION"
echo "
βœ…βœ…βœ…βœ… NOTARIZATION COMPLETE - UPLOAD ZIP TO ITCH.IO, etc.
"
@omundy
Copy link
Author

omundy commented Oct 9, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment