PWA iOS limitations are restrictions that Apple's Safari browser and iOS impose on progressive web apps, blocking access to device features, background tasks, and system integrations that native iOS apps can use freely. iOS 16.4 brought push notification support — a major step forward. But PWAs on iPhone and iPad still face tight limits on hardware access, offline storage, background processing, and full-screen experiences compared to Android and desktop.
If you're building a PWA, you need to know what iOS blocks and what it allows. This guide covers every major limitation, shows what works across iOS versions, gives you code workarounds, and helps you decide when a PWA is enough — and when you need a native app.
Not sure if you should build a PWA at all? See our PWA vs Native App decision guide first.
How iOS PWA Support Got Here
Apple has moved slowly on PWAs compared to Google. Here's the timeline:
2017-2018: iOS 11.3 added basic service worker support. No push notifications. No background sync. Cached data expired after 2 weeks.
2020-2021: iOS 13 improved offline support and caching. Still no push or background features.
2023 (iOS 16.4): The biggest change in years. Push notifications arrived. Safari got the Web Push API. The Badging API landed. Manifest handling improved.
2024 (iOS 17.4): Apple removed standalone PWA support in the EU under the Digital Markets Act. PWAs in EU countries now open in Safari tabs with no push support.
2026: Push works on iOS 16.4+ outside the EU. Service workers run but with limits. Storage quotas are tighter than Chrome. Many Web APIs remain missing.
Why Apple Holds Back
Four factors explain Apple's caution:
- App Store revenue. PWAs skip the App Store and its 15-30% commission.
- Security control. Apple prefers tight control over what code runs on devices.
- UX standards. Apple worries that low-quality PWAs could hurt the iOS brand.
- WebKit monopoly. All iOS browsers must use WebKit. Apple controls which web features reach iPhone and iPad.
Every iOS PWA Limitation
Push Notifications on iPhone
Status: Partially supported (iOS 16.4+, outside EU)
What works:
- Basic push notifications on iOS 16.4 and later.
- Web Push API in Safari.
- Background delivery and notification actions.
What doesn't:
- Needs iOS 16.4 or later (March 2023 release).
- The PWA must be installed to the home screen first.
- Not available in EU countries (iOS 17.4+).
- No automatic install prompts — users must add it manually.
Workaround: Detect iOS and show custom install instructions. Fall back to email or SMS for users on older iOS versions.
function isIOSWithoutPushSupport() {
const ua = navigator.userAgent;
const iOS = /iPad|iPhone|iPod/.test(ua);
if (!iOS) return false;
const isInstalled = window.navigator.standalone === true;
const version = parseFloat((ua.match(/OS (\d+)_(\d+)/) || [0, 0])[1]);
return version < 16.4 || !isInstalled;
}
if (isIOSWithoutPushSupport()) {
showIOSInstallPrompt();
}
For the full setup, see our guide to push notifications in PWAs.
Home Screen Installation
Status: Manual only — no browser prompts
What works:
- Users can add PWAs to their home screen manually.
- PWAs launch in standalone mode (no Safari UI).
- Custom splash screens and app icons appear.
What doesn't:
- No automatic install prompts on iOS.
- No
beforeinstallpromptevent support. - EU users get a browser-tab experience (iOS 17.4+).
Make sure your web app manifest is set up correctly with the right icons, display mode, and theme colors. Use the PWA icon generator for a full icon set.
Workaround: Show custom install instructions for iOS users:
function showIOSInstallInstructions() {
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
const isInstalled = window.navigator.standalone === true;
if (isIOS && !isInstalled) {
return {
show: true,
instructions: [
'Tap the Share button in Safari',
'Scroll down and tap "Add to Home Screen"',
'Tap "Add" in the top right corner',
],
};
}
return { show: false };
}
Storage and Caching
Status: Works, but with strict limits
What works:
- Service worker caching, IndexedDB, LocalStorage, and Cache API.
What doesn't:
- 7-day cache expiry. If a user doesn't open your PWA for a week, all cached data is gone.
- 50MB storage cap. Chrome allows hundreds of MB. Safari caps it at 50MB.
- Aggressive cleanup. iOS deletes cached data when the device runs low on space.
- No persistent storage guarantee. Clearing Safari history also clears PWA caches.
This is one of the biggest pain points. Users who skip your PWA for a week lose all offline content.
Workaround: Re-cache key assets every time the app launches:
const CRITICAL_CACHE = ['/', '/app-shell.html', '/critical.css', '/critical.js'];
async function ensureCriticalAssetsCached() {
const cache = await caches.open('critical-v1');
await cache.addAll(CRITICAL_CACHE);
}
window.addEventListener('load', ensureCriticalAssetsCached);
For deeper strategies, see Offline-First PWAs: Service Worker Caching Strategies.
Background Processing
Status: Not supported
None of these work on iOS:
- Background Sync API
- Periodic Background Sync
- Background Fetch
Impact: Your PWA can't sync data when closed, upload files in the background, update content on a schedule, or retry failed requests automatically.
Workaround: Sync when the app is open:
window.addEventListener('online', async () => {
await syncPendingData();
});
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
syncPendingData();
}
});
Hardware and Sensor Access
Status: Mostly unsupported
Not supported: Web Bluetooth, Web NFC, Web USB, Web Serial, Generic Sensor API, Ambient Light Sensor, Proximity Sensor.
Partially works: Geolocation (needs permission each session), Device Orientation (less reliable than Android), Camera/Microphone (needs permissions).
Bottom line: If your app needs Bluetooth, NFC, or USB connections, build a native app. There's no workaround.
Full-Screen Experience
Status: Partially supported
Standalone mode works — no Safari UI when installed. Custom splash screens and status bar theming work. But there's no true fullscreen API. The status bar always shows. Notched devices need safe area insets. No immersive mode like Android.
Workaround: Design for safe areas:
.header { padding-top: env(safe-area-inset-top); }
.footer { padding-bottom: env(safe-area-inset-bottom); }
body {
padding: env(safe-area-inset-top) env(safe-area-inset-right)
env(safe-area-inset-bottom) env(safe-area-inset-left);
}
Badges and Shortcuts
The Badging API works on iOS 16.4+ — you can set a number on the home screen icon. But app icon shortcuts (long-press menu), dynamic shortcuts, and widgets are not supported.
if ('setAppBadge' in navigator) {
navigator.setAppBadge(5);
navigator.clearAppBadge();
}
File System and Contacts
File System Access API: Not supported. No read/write to files. The basic file input picker (read-only) and Web Share API work.
Contact Picker API: Not supported. Build custom forms instead.
Payments
The Payment Request API works, including Apple Pay. But you can't bypass the App Store for digital goods (policy, not technical). For physical goods, use Stripe or another web payment processor.
iOS Version Matrix
| Feature | iOS 15 | iOS 16.0-16.3 | iOS 16.4+ | iOS 17+ (non-EU) | iOS 17+ (EU) |
|---|---|---|---|---|---|
| Service Workers | Yes | Yes | Yes | Yes | Yes |
| Web App Manifest | Yes | Yes | Yes | Yes | Partial |
| Push Notifications | No | No | Yes | Yes | No |
| Badging API | No | No | Yes | Yes | No |
| Standalone Mode | Yes | Yes | Yes | Yes | No |
| Offline Support | Yes | Yes | Yes | Yes | Yes |
| Background Sync | No | No | No | No | No |
| Web Bluetooth | No | No | No | No | No |
| 7-Day Cache Limit | Yes | Yes | Yes | Yes | Yes |
Minimum recommendation: iOS 16.4 for push notifications. iOS 15+ for basic PWA features.
EU Digital Markets Act Impact
In March 2024, Apple changed how PWAs work in the EU to comply with the DMA.
What changed (iOS 17.4, EU only):
- PWAs no longer run in standalone mode.
- All PWAs open in Safari tabs.
- Push notifications don't work.
- Home screen icons just open Safari.
- Badges don't work.
Why: Apple says the DMA requires supporting non-WebKit browser engines. Rather than build multi-engine PWA support, Apple removed PWA features in the EU.
What you can do about it: Nothing technical. Your options are:
- Accept the browser-based experience for EU iOS users.
- Build a native iOS app for the EU market.
- Focus the PWA on non-EU markets and Android.
EU detection (approximate):
function isEURegion() {
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const euTimezones = [
'Europe/Brussels', 'Europe/Paris', 'Europe/Berlin',
'Europe/Madrid', 'Europe/Rome', 'Europe/Amsterdam',
];
return euTimezones.includes(timezone);
}
Use server-side geolocation for accuracy. Timezones are rough estimates and VPNs can mislead.
Safari Quirks That Affect PWAs
Beyond the major limits, Safari has smaller bugs that trip up PWA developers.
Viewport Height
100vh includes Safari's bottom bar, which causes layout jumps.
.full-height {
height: 100vh;
height: -webkit-fill-available;
}
Autoplay
Safari blocks video autoplay unless the user has interacted with the page. Muted videos can autoplay.
Service Worker Caching
Safari caches service workers more aggressively than Chrome. Force an update check:
navigator.serviceWorker.getRegistration().then((reg) => reg.update());
Scroll Momentum
Use -webkit-overflow-scrolling: touch for smooth scrolling in overflow containers.
Feature Detection Code
Detect iOS and feature support before using PWA APIs:
const PWACapabilities = {
isIOS: () => /iPad|iPhone|iPod/.test(navigator.userAgent),
isInstalled: () => {
if (window.navigator.standalone === true) return true;
if (window.matchMedia('(display-mode: standalone)').matches) return true;
return false;
},
iOSVersion: () => {
const match = navigator.userAgent.match(/OS (\d+)_(\d+)/);
if (!match) return null;
return { major: parseInt(match[1]), minor: parseInt(match[2]) };
},
supportsPush: () => {
if (!('PushManager' in window)) return false;
const version = PWACapabilities.iOSVersion();
if (!version) return true;
return version.major > 16 || (version.major === 16 && version.minor >= 4);
},
};
if (PWACapabilities.isIOS() && !PWACapabilities.supportsPush()) {
// Show alternative engagement methods
}
Best Practices for iOS PWA Development
Build with Progressive Enhancement
Start with features that work everywhere. Add push, badges, and other extras only when the browser supports them:
if (PWACapabilities.supportsPush()) {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: vapidPublicKey,
});
await sendSubscriptionToServer(subscription);
}
Teach Users How to Install
Most iPhone users don't know they can install PWAs. Show clear, step-by-step instructions: tap Share, then "Add to Home Screen", then "Add."
Fight the 7-Day Cache Limit
Re-cache critical assets on every launch. Keep your cache small (under 50MB). Assume the cache is empty and handle cache misses gracefully.
Handle Offline Gracefully
Since background sync doesn't work, save failed requests to IndexedDB and retry when the app comes back online:
window.addEventListener('online', async () => {
const pending = await getAllFromIndexedDB('pending-submissions');
for (const item of pending) {
await submitForm(item);
await deleteFromIndexedDB('pending-submissions', item.id);
}
});
Test on Real iPhones
Simulators miss real-world PWA behavior. Test on iOS 16.4+ for push. Test after 7+ days of inactivity for cache expiry. Test the install flow. Test on devices with a notch.
When to Build a Native iOS App Instead
Some use cases demand native. Build a native iOS app when:
- Hardware access is critical — Bluetooth, NFC, AR, USB.
- Background processing is required — location tracking, data sync, VoIP.
- Performance is paramount — 3D games, video processing, heavy animation.
- Deep iOS integration is needed — widgets, live activities, Siri.
- EU is your primary market — iOS PWA features don't work in the EU.
For a complete decision framework comparing PWAs and native apps, see our PWA vs Native App guide.
What's Improving
Despite the limits, Apple is slowly moving forward:
Recent gains (2023-2025): Push notifications (iOS 16.4). Badging API. Better manifest support. More stable service workers.
Possible soon: Better storage quotas. Longer cache persistence. EU PWA support restored (uncertain).
Unlikely soon: Background Sync. Web Bluetooth/NFC. Automatic install prompts. Fullscreen API.
Keep watching: WebKit Feature Status tracks what's in development. Major PWA changes usually arrive with major iOS versions (16.0, 17.0, etc.).
Choosing the Right Approach for Your App
Content and E-commerce Apps
Good fit for an iOS PWA. Offline catalog browsing, fast caching, and push notifications (iOS 16.4+) all work. Lower development costs. Consider native only if you need AR try-on or similar hardware features.
Social and Messaging Apps
Marginal fit. No background sync hurts message delivery. Cache expiry impacts message history. Consider a native app for iOS with a PWA for Android and desktop.
Productivity Tools
Depends on features. Cloud-based tools (like Google Docs) work well as PWAs. Tools that need file system access or background sync should go native.
Field Service Apps
Poor fit. No background location, no background sync, and 7-day cache expiry make this impractical. Build native for the mobile app, PWA for the admin portal.
For more implementation tips, see Essential PWA Strategies for Enhanced iOS Performance.
Conclusion
PWA development for iOS means working within real limits. Push arrived in iOS 16.4, but storage, background tasks, and hardware access remain restricted.
Key takeaways:
- iOS 16.4+ is required for push. That's the minimum for notification-dependent apps.
- The 7-day cache limit is real. Design for re-caching on every launch.
- Background tasks don't work. Sync must happen while the app is open.
- EU users lose PWA features. Plan for regional alternatives.
- Hardware-heavy apps need native. Bluetooth, NFC, and sensors are unavailable.
- Installation is manual only. You must teach iPhone users how to install.
With these limits understood, you can build PWAs that work well on iOS — while keeping expectations realistic about what the platform can do.
Frequently Asked Questions
Will Apple ever fully support PWAs like Chrome?
Unlikely soon. Apple's App Store revenue and platform control make full parity improbable. But Apple keeps making small improvements. Push notifications in iOS 16.4 were a big step. Expect slow, steady progress rather than sudden change.
How do I handle the 7-day cache expiry?
Re-cache critical assets on every app launch. Keep your cache small. Prioritize the app shell (HTML, CSS, JS) over content. Assume the cache is empty and handle misses gracefully. Don't store large media files in the service worker cache.
Should I build separate apps for iOS and Android?
Not always. Build a PWA first and see if iOS limits affect your core use case. Many apps work fine within iOS constraints. Build a native iOS app only if the limits create real user experience problems.
Does a WKWebView wrapper bypass these limits?
Partially. Frameworks like Capacitor or Cordova use WKWebView and can access native iOS APIs. But you must distribute through the App Store (losing PWA's install simplicity) and follow App Store review rules.
Can I embed PWA content in a native iOS app?
Yes. WKWebView lets you embed web content in a native app. This hybrid approach uses web tech for content while accessing native features through JavaScript bridges. Popular frameworks: Capacitor, Cordova, React Native WebView.
Is the EU PWA restriction permanent?
Unknown. Apple removed PWA features in iOS 17.4 citing DMA compliance. EU regulators are investigating. The restriction could be reversed if regulatory pressure grows, but there's no timeline.
Why doesn't Apple support automatic PWA install prompts?
Apple hasn't said officially. Likely reasons: protecting App Store revenue, preventing spam prompts, maintaining UX quality, and avoiding prompt fatigue for users.
Can I detect if a user is in the EU?
Timezone detection gives a rough guess. Server-side IP geolocation is more accurate but VPNs can mislead. The safest approach: design your PWA to work without standalone mode and treat standalone as an extra feature.
