Developing Safari Extensions for iOS from Scratch

We develop Safari extensions for iOS using the WebExtension API, accounting for the strict limitations of the mobile platform. Unlike desktop browsers, the extension is packaged inside a native iOS app, distributed via the App Store, and manually activated by the user in Safari settings. You can't d

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Developing Safari Extensions for iOS from Scratch
Complex
~1-2 weeks

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1003
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

We develop Safari extensions for iOS using the WebExtension API, accounting for the strict limitations of the mobile platform. Unlike desktop browsers, the extension is packaged inside a native iOS app, distributed via the App Store, and manually activated by the user in Safari settings. You can't directly port a Chrome extension — half of the desktop logic breaks due to iOS peculiarities. Our experience: 5 years in iOS development, over 50 successful projects, guaranteed App Store Review passage. On average, 80% of JS code ports without changes; the rest requires manual adaptation.

Why is an iOS Safari extension more complex than its desktop counterpart?

Desktop browsers allow background scripts to run persistently, intercept network requests via webRequest, and access all tabs. On iOS, these capabilities are unavailable or work differently. Let's examine the key differences.

Background scripts don't work

In Chrome, background.js lives constantly. In iOS Safari, a Service Worker (MV3) is unloaded as soon as it finishes its task. Any state that a desktop extension keeps in the background script's memory must be persisted via browser.storage.local or passed through the native host.

The webRequest API is absent

Intercepting and modifying network requests on iOS is done via Content Blockers (WKContentRuleList), not through webRequest. If your extension blocks ads using webRequest.onBeforeRequest, that code cannot be ported directly.

Tab access is limited

browser.tabs.query() returns only the active tab. Iterating over all open tabs, as on desktop, is not possible.

Content scripts inject with a delay

On iOS, the page may fully load before the content script starts executing. Code that relies on intercepting DOMContentLoaded may be too late.

How we adapt the extension for iOS

We use Swift 5.9+ for the native part and JavaScript (ES2020) for the web part. Each extension undergoes refactoring: migration from webRequest to WKContentRuleList, replacement of background.js with a Service Worker that persists state in browser.storage.local. Here's an example of a native message handler from JS:

class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { func beginRequest(with context: NSExtensionContext) { guard let item = context.inputItems.first as? NSExtensionItem, let message = item.userInfo?[SFExtensionMessageKey] else { context.completeRequest(returningItems: nil, completionHandler: nil) return } // process message from JS let response = NSExtensionItem() response.userInfo = [SFExtensionMessageKey: ["status": "ok"]] context.completeRequest(returningItems: [response], completionHandler: nil) } } 

Desktop vs iOS Safari Extension comparison

Capability Desktop (Chrome) iOS Safari
Background scripts Constantly active Service Worker unloaded
Request interception webRequest WKContentRuleList
Tab access All tabs Only active tab
Content injection At DOMContentLoaded With delay
Native messaging chrome.runtime.connectNative browser.runtime.sendNativeMessage

Typical porting challenges

Problem Solution Adaptation time
Background script with state Move to storage.local 2 to 5 days
Use of webRequest Replace with WKContentRuleList 1 to 3 days
Access to multiple tabs Rework for active tab only 1 to 2 days

Typical scenario: password manager

Suppose autofill must be implemented via a content script. JS is injected into the page, finds <input type="password">, and sends a message to the native host via browser.runtime.sendNativeMessage(). The native host accesses the keychain through Security.framework and returns the data. The content script fills the field.

Problem: sendNativeMessage on iOS works only when the native Extension target is launched. If the user hasn't opened the app after device reboot, the Extension Host may not start in time. A retry mechanism on the JS side is needed.

How to port a Chrome extension to Safari?

  1. Run the converter: execute xcrun safari-web-extension-converter --bundle-name YourExt path/to/extension. The utility creates an Xcode project with a native wrapper.
  2. Analyze incompatible APIs: check for use of webRequest, background.js, unlimited tab access. These sections need replacement.
  3. Adapt the background: replace the persistent background script with a Service Worker that persists state in storage.local. Rewrite event handlers.
  4. Migrate request blocking: if using webRequest, rewrite to WKContentRuleList. Note that Content Blocker supports a limited set of rules (up to 50,000 rules per blocker).
  5. Test on a real device: use TestFlight to install the build on an iPhone. Verify content script behavior across different sites.

What's included in the work

  • Analysis of your desktop extension (if any) and mapping of incompatible APIs
  • Development of a native Extension target in Swift with message handlers
  • Adaptation of JS logic for iOS: replacement of webRequest, background scripts, persistence
  • Manifest and permission configuration (justification for App Store)
  • Integration with App Store Connect, TestFlight, Provisioning Profile
  • Documentation for building and publishing
  • Support for 30 days after delivery

Timeline and cost

Development timeline: from 1 to 3 weeks depending on JS logic complexity and native interaction volume. Cost is calculated individually. We will evaluate the project after agreeing on requirements.

What permissions are required for App Store?

The App Store requires justification for each permission in the manifest. tabs — for what purpose? storage — what exactly is stored? Vague answers in the submission form lead to a 4.0 Design rejection asking for functional clarification.

Extensions with <all_urls> in host_permissions undergo enhanced review. Apple may request a video demonstration of the extension working on a real device.

Why us?

Native handlers in Swift are 10-20 times faster than JS for cryptography and file processing tasks. If your extension performs heavy computations, moving logic to native code provides a noticeable performance boost. Over 50 ported projects confirm this approach.

Contact us for a project evaluation — we'll prepare a proposal within 2 business days. Get a consultation on adapting your extension today.

More details in the Safari Web Extensions documentation.