Browser extensions · Updated

Publish a Safari extension to the Mac App Store (distribution checklist)

Ship a Safari Web Extension on macOS: Apple Developer Program, Xcode archive, App Store Connect, review tips, and Payhook hosted checkout for Pro without in-popup payments.

#safari#macos#app-store#publishing#distribution


Local testing - Run in Xcode and enable the extension in Safari → Settings → Extensions - is only step one. To distribute a Safari Web Extension to other Mac users at scale, you typically publish the containing macOS app through the Mac App Store (or notarize for direct download). Apple’s rules differ from Chrome Web Store or AMO; payments for Pro features still flow through your Stripe account + Payhook, not an Apple extension IAP you can count on for arbitrary SaaS-style unlocks.

Start with Safari Web Extension Manifest V3 starter or Create a Safari extension with Claude Code if you have not built the project yet.

What Apple expects

ItemNotes
Apple Developer ProgramAnnual membership for App Store distribution
Xcode Safari Web Extension App targetEmbeds your WebExtension resources
App icons, screenshots, descriptionApp Store Connect metadata
Privacy policyEspecially if you sync data or open external checkout
Accurate App Privacy labelsDeclare data collected by the app and extension

Safari Web Extensions reuse your MV3 web code; native Swift in the wrapper is usually minimal.

Step 1 - Enroll and configure signing

  1. Enroll in the Apple Developer Program with the same Apple ID you use in Xcode
  2. In Xcode, select the app target → Signing & Capabilities
  3. Choose your Team and enable automatic signing for development
  4. Set a unique Bundle Identifier (e.g. com.yourname.focustab)

Fix signing errors with Xcode’s Issue navigator - paste errors into your AI assistant with macOS and Xcode versions.

Step 2 - Prepare App Store metadata

In App Store Connect:

  1. Create a new macOS app record matching your bundle ID
  2. Write a clear description of what the Safari extension does (users care about the extension, not the wrapper app)
  3. Add screenshots showing the popup and a key feature on a real website
  4. Link your privacy policy (required for most monetized tools)
  5. Complete App Privacy and age rating questionnaires

Step 3 - Archive and upload

  1. In Xcode, set scheme to Any Mac (Apple Silicon, Intel) or your supported architectures
  2. Product → Archive
  3. In the Organizer window, Distribute AppApp Store Connect → Upload
  4. Wait for processing in App Store Connect (often 10-30 minutes)

Submit for review when the build appears. Review length varies; rejections often cite metadata, privacy, or unclear extension permission usage - respond with concise fixes.

Monetization and App Review

For Pro tiers, the pattern App Review tends to accept for indie extensions:

  • Free core features in the extension
  • Upgrade opens Safari to a hosted Stripe checkout page (Payhook)
  • Pro unlock via entitlement checks after payment - no card numbers in the popup

Setup: Stripe account for extension creatorsPayhook unlock quickstart.

Explain in review notes where checkout happens and that payment is processed by Stripe, not inside the extension sandbox.

Note: Mac App Store in-app purchase rules apply to apps sold through Apple’s IAP system. Most Payhook extension builders use external hosted checkout for Pro on the web stack - confirm your product story matches current Apple guidelines for your category; when in doubt, describe the flow plainly in App Review notes.

Direct download alternative

Some teams ship outside the Mac App Store with notarized disk images. That path still requires Developer ID signing and notarization. Distribution and payment story remain your responsibility - Payhook checkout works the same.

Update releases

  1. Increment CFBundleShortVersionString (app) and extension version in manifest.json
  2. Archive and upload a new build
  3. Submit release notes in App Store Connect

Cross-browser strategy

Ship Safari after Chrome or Firefox validation. Ask your agent:

Keep Shared WebExtension files identical across Chrome, Firefox, and Safari wrapper; document Safari-only API limits in README.

Next steps