While implementing Apple Maps into our web application, I have a scenario where I want to be able to drag and move some of my custom annotations around. While that is working, when "picking up" the annotation before dragging it, there is an animation which I believe is to represent the human interaction of picking up a pin from a map, I would like to cancel that animation and thought that would be possible by calling preventDefault() in the emitted long-press event, which the documentation states that annotations should emit if they are draggable. The thing is that I don't get this event to emit when long pressing an annotation. So I believe that I have found a bug.
It's in this paragraph in the documentation https://developer.apple.com/documentation/mapkitjs/handling-map-events#Respond-to-map-interaction-events
A long press occurs on the map outside an annotation. A long press may be the beginning of a panning or pinching gesture on the map. You can prevent the gesture from starting by calling the preventDefault() method of the event. Annotations need to be draggable to dispatch long-press events.
In anybody else experiencing this or do you see any clear fix for this? Maybe there is another way to cancel that "picking up the annotation for dragging" animation. I have seemed to try anything else.
General
RSS for tagExplore the integration of web technologies within your app. Discuss building web-based apps, leveraging Safari functionalities, and integrating with web services.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
YouTube now requires a Referer to be sent to be able to embed Youtube videos, otherwise the videos won't work. But WKWebView doesn't send a Referer when using a custom scheme, so Youtube videos stopped working in that case.
This affects Ionic apps, both using Cordova or Capacitor. There's an open issue for Cordova and another one for Capacitor. In these apps, the app is served using a custom scheme like capacitor://localhost or ionic://localhost.
I tried modifying the Ionic WebView source code to force adding a referrer to the URL loaded using WKWebView's loadRequest:
[request addValue:@"https://my.test.app" forHTTPHeaderField:@"Referer"];
[_engineWebView loadRequest:request]
But the Referer is still not sent in the Requests, I guess because the app is using a custom scheme (e.g. capacitor://localhost). However, if I modify this code to force loading an "online URL" (using https) instead of capacitor://localhost, then the my.test.app Referer is sent to the requests.
Is there any way to make WKWebView send a Referer when using a custom scheme?
I have a visionOS app using Apple's WebView and WebPage to display web content. When viewing a live YouTube stream last night, YouTube put up the warning in the area that would have the chat window:
Oh no!
It looks like you're using an older version of your browser. Please update it to use live chat.
Anyone know if YouTube is generating this from the server based on the WebPage's user agent string, from Javascript running in the browser engine, or something else?
Anyone know if and how it is possible to resolve this?
(See right side of YouTube web page from a screen grab):
Dears,
We are facing some issue in ios 18.4.1. Recently some of our end users who updated their ios devices to 18.4.1 have experienced random 403 errors in runtime. as per our analysis, We identified that these errors are associated with "CSRF token mismatch".
After successful login, the user's CSRF token is causing issue and it was changed in runtime, this causes the cookie mismatch, and the users is getting 403 errors, and the user session is getting invalid suddenly.
let me know if anyone facing the same issue in ios 18.4.1 and let me know Is there any workaround for this issue.
Thanks.
Steps to Reproduce
1. Create a native UIViewController with a WKWebView, loading test-1.html (contains position:fixed header that displays correctly).
2. Push another UIViewController also with a WKWebView, this time loading test-2.html.
3. In test-2.html, tap into the to summon the on-screen keyboard.
4. Without calling blur(), perform an interactive swipe-back gesture to go back to the first view controller.
5. Observe that the fixed header in test-1.html is now offset downward by approximately the height of the keyboard and does not return to its original position.
demo-link : https://bugs.webkit.org/attachment.cgi?id=476324
I want to confirm the specifications and behavior of Safari.
We have a system built on Microsoft Azure that uses Azure AD B2C for authentication.
When we logging in, there is a phone authentication feature where a call is made to the registered phone number.
However, this phone authentication does not work properly only on iPhone's Safari. The specific situation is listed below:
When performing phone authentication on iPhone's Safari, a call is made from Azure AD B2C, and pressing the # button on the Safari screen can be done. But then, it transitions to an error screen.
We tried multiple iPhone devices and multiple iOS versions, but the result was the same.
But when accessing the system on a PC, and performing phone authentication, it works without any errors.
Also when we use browsers other than Safari (for example, Google Chrome and Firefox) on the iPhone, the phone authentication works without any errors, too.
Even with Safari, if the device displaying the login screen and the device making the call are different, phone authentication works without any errors, too.(it fails if they are the same device).
We reached out Microsoft about this issue, and they responded that:
The Azure resource called FrontDoor at the front end of Azure AD B2C supports the HTTP/2 protocol, and HTTP/2 protocol is used in communication with Safari.
In Safari's HTTP/2 communication, when a call is received while the screen is displayed, a reset packet is sent to the web server (in this case, the web server is FrontDoor).
This interrupts the session, causing a session termination error on the Azure AD B2C side, and phone authentication fails.
Therefore, we would like to ask you the following two points:
In HTTP/2 communication, does the Safari browser send a reset packet to the web server when it receives a phone call?
If so, what is the cause of this behavior? And are there any measures to prevent the reset packet from being sent?
Topic:
Safari & Web
SubTopic:
General
Hi all,
I'm developing an application that uses WKWebView to display a web application which I augment with iOS native utilities such as Speech to Text and IAP. The application also uses Service workers, so we define AppBound Domains in the info.plist file.
Everything works for this, but when we deploy on a device the application will crash and say we need these entitlements
com.apple.developer.web-browser-engine.networking,
com.apple.developer.web-browser-engine.rendering,
com.apple.developer.web-browser-engine.webcontent,
com.apple.runningboard.assertions.webkit
From what I can see, we do need all of them. However Apple suggest submitting a request to be an Altnerative Browser (https://developer.apple.com/support/alternative-browser-engines)
This is not appropriate for the application in my view since one requirement of being an alternative browser is that you don't modify the resources on the web site - we of course do since we inject javascript in order to bridge between iOS and the contents of the webview.
How are people navigating this issue? I assumed it would be common given the use of Tauri etc. to build similar types of applications, but I don't see much about it.
Thank you!
Description:
In our app, we have login page which displayed in WKWebView. In that page, there is an Remember my Device cookie option which user can select, so next time it OTP page will not be displayed.
Problem Statement:
Recently we found that some issue happened with this cookie. Especially, when users upgraded their OS versions to 18.6 or 26.1 or 26.2.
Need to understand, any changes related to Cookie part in latest OS Versions?
Topic:
Safari & Web
SubTopic:
General
ios drop file wrong file name
I use the following simple JS code to drag file from the browser to the desktop.
Works perfect on MacOS.
onDragStart(event, ucpView) {
let file = new BrowserFile([this.file.fileContent], this.file.displayName, {
type: 'application/ucp-scenario'
});
const fileURL = URL.createObjectURL(file);
event.dataTransfer.setData("DownloadURL", `application/octet-stream:${file.name}:${fileURL}`);
event.dataTransfer.setData("text/uri-list", fileURL);
}
but on iOS it keeps nameing the file
Text1.txt
Text2.txt
...
and ignores the DownloadURL
whats the best way to get it workng on both OS?
Topic:
Safari & Web
SubTopic:
General
Hello everyone,
We've had our app rejected twice under Guideline 3.2.2 regarding charitable donations, and we're seeking clarification on the correct implementation. We've read the guidelines but want to confirm the technical approach with the community's experience.
The Rejection Reason:
Apple states: "We still noticed that your app includes the ability to collect charitable donations within the app..." They specify that since we are not an approved nonprofit, we must use one of the alternatives, primarily: "provide a link to your website that launches the default browser or SFSafariViewController for users to make a donation."
Our Current (Rejected) Implementation:
User taps a "Help" button in our native app.
A native modal appears inside our app where the user enters their donation amount and email address for the receipt.
The user clicks "Donate," which then opens an SFSafariViewController to our website's payment page (e.g., Stripe, PayPal). The amount and email are passed as URL parameters to pre-fill the form.
Our Questions for the Community:
Is the issue solely the fact that we have a native modal for data entry? We understand we cannot process the payment in-app, but we thought collecting the intent (amount, email) was acceptable before handing off to Safari.
What is the definitive, compliant flow?
Option A: Should the "Help" button do nothing more than open an SFSafariViewController to a generic donations landing page on our website (https://ourwebsite.com/donate), with no data pre-filled? The user must then navigate and enter all information on the website itself.
Option C: The rejection also mentions SMS. Has anyone had success implementing a "Text-to-Donate" link instead of a web flow?
Wording: The button in our app currently says "Donate". Should this be changed to a more passive call to action like "Visit Website to Donate" to make it absolutely clear the transaction is external?
We want to ensure our next submission is successful. Any insight, especially from developers who have successfully navigated this exact rejection, would be immensely helpful.
Thank you.
Dear Apple Developer Support Team,
I am writing regarding critical issues we are facing with Safari web push notifications in our application iLiveMyLife.io, which is severely impacting our ability to maintain reliable communication with our users.
Issue Description:
We are experiencing persistent problems with Safari push notification tokens expiring or becoming invalid without any notification to our server. This creates several critical issues:
Users stop receiving notifications without any indication of failure
Our notification delivery system has no way to detect token expiration
The expiration appears to happen frequently (seemingly almost daily in some cases)
There is no reliable mechanism to re-establish push communication without users manually revisiting the app
Technical Impact:
Our messaging functionality becomes completely unreliable
We must resort to email or SMS as fallback mechanisms, which is not feasible for a real-time communication platform
This makes building any reliable messaging application on Safari practically impossible
The Broader Context:
What makes this situation particularly challenging is that all potential alternative browser APIs that could help address this issue appear to be deliberately disabled or restricted in Safari:
Background Service Workers don't function in the background on iOS Safari
Background Sync API is not supported
WebSockets cannot operate when the app is closed
There's no way to programmatically check the validity of push tokens
The combination of these limitations creates a situation where developers have no viable technical path to build reliable notification systems for PWAs on Safari. This appears to be a systematic restriction rather than individual API limitations.
Requested Information:
Is there a recommended approach to detect Safari push token expiration?
Are there alternative notification mechanisms for PWA applications on Safari that offer more reliability?
Is there documentation on the lifecycle of Safari push tokens that could help us implement proper handling?
Are there plans to improve the Web Push API implementation in Safari to address these reliability issues?
Could you clarify if these limitations are intentional design decisions or technical constraints that might be addressed in future updates?
Business Impact:
This issue fundamentally undermines our platform's core functionality. For a collaborative tool, reliable notifications are essential - users cannot collaborate effectively if they miss updates because their push tokens silently expired. The current state creates confusion among our users, who don't understand why they suddenly stop receiving notifications.
Any guidance or assistance you could provide would be greatly appreciated. We're committed to providing an excellent experience on Safari, but the current push notification limitations make this extremely challenging.
Thank you for your time and consideration.
Best regards,
Ilya
Hi everyone,
I want users not to see the system context menu when long-pressing text on a page in Safari on iOS. I found on MDN that the CSS property -webkit-touch-callout: none; can achieve this. But in reality, it doesn't really work.
MDN documents URL: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/-webkit-touch-callout
Here’s a minimal example:
function preventIOSSafariContextMenu() {
if (document.getElementById(STYLE_ELEMENT_ID)) return;
if (!IS_TOUCH_DEVICE) return;
const style = document.createElement("style");
style.id = STYLE_ELEMENT_ID;
style.textContent = `
html, body {
-webkit-touch-callout: none !important;
}
`;
(document.head || document.documentElement).appendChild(style);
}
The context menu persists.
Has anyone else encountered this? Is this an intentional change in WebKit, or could it be a regression? If it’s intentional, is there a recommended alternative?
Thanks in advance for any insights!
Hello Community,
My application was rejected by Apple App Review, citing Guideline 4.7 and "non-embedded," which I believe is incorrect. All transactions are signed and sent directly through the app with explicit user permission. Additionally, there's an issue with min apps where users can access the functionality via a browser to interact with the service. This feature has been part of my old application and hasn't changed in the new update. It’s the same functionality as used by popular wallets like
Metamask
Uniswap
Coinbase
Which also employ web3 technology.
Over the past two weeks, I've tried to communicate with Apple's support team but have been ignored or received only generic rejection emails. This has left me frustrated and concerned about the time and resources I’ve invested in developing and supporting this app.
Could you please help me find a solution? Your assistance would be greatly appreciated!
I'm building a Capacitor iOS app with a plain <video> element playing an MP4 file inline. I want Picture-in-Picture to activate automatically when the user goes home — swipe up from the bottom edge of the screen (on an iPhone with Face ID) or press the Home button (on an iPhone with a Home button).
Fullscreen → background works perfectly — iOS automatically enters Picture-in-Picture. But I need this to work from inline playback without requiring the user to enter fullscreen first.
Setup
<video id="video" playsinline autopictureinpicture controls
src="http://podcasts.apple.com/resources/462787156.mp4">
</video>
// AppDelegate.swift
let audioSession = AVAudioSession.sharedInstance()
try? audioSession.setCategory(.playback, mode: .moviePlayback)
try? audioSession.setActive(true)
UIBackgroundModes: audio in Info.plist
allowsPictureInPictureMediaPlayback is true (Apple default)
iOS 26.3.1, WKWebView via Capacitor
What I've tried
1. autopictureinpicture attribute
<video playsinline autopictureinpicture ...>
WKWebView doesn't honor this attribute from inline playback. It only works when transitioning from fullscreen.
2. requestPictureInPicture() on visibilitychange
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden' && !video.paused) {
video.requestPictureInPicture();
}
});
Result: Fails with "not triggered by user activation". The visibilitychange event doesn't count as a user gesture.
3. webkitSetPresentationMode('picture-in-picture') on visibilitychange
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden' && !video.paused) {
video.webkitSetPresentationMode('picture-in-picture');
}
});
Result: No error thrown. The webkitpresentationmodechanged event fires with value picture-in-picture. But the PIP window never actually appears. The API silently accepts the call but nothing renders.
4. await play() then webkitSetPresentationMode
document.addEventListener('visibilitychange', async () => {
if (document.visibilityState === 'hidden') {
await video.play();
video.webkitSetPresentationMode('picture-in-picture');
}
});
Result: play() succeeds (audio resumes in background), but PIP still doesn't open.
5. Auto-resume on system pause + PIP on visibilitychange
iOS fires pause before visibilitychange when backgrounding. I tried resuming in the pause handler, then requesting PIP in visibilitychange:
video.addEventListener('pause', () => {
if (document.visibilityState === 'hidden') {
video.play(); // auto-resume
}
});
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden' && !video.paused) {
video.webkitSetPresentationMode('picture-in-picture');
}
});
Result: Audio resumes successfully, but PIP still doesn't open.
6. Native JS eval from applicationDidEnterBackground
func applicationDidEnterBackground(_ application: UIApplication) {
webView?.evaluateJavaScript(
"document.querySelector('video').requestPictureInPicture()"
)
}
Result: Same failure — no user activation context.
Observations
The event order on background is: pause → visibility: hidden
webkitSetPresentationMode reports success (event fires, no error) but the PIP window never renders
requestPictureInPicture() consistently requires user activation, even from native JS eval
Audio can be resumed in background via play(), but PIP is a separate gate
Fullscreen → background automatically enters Picture-in-Picture, confirming the WKWebView PIP infrastructure is functional
Question
Is there any way to programmatically enter PIP from inline playback when a WKWebView app goes to background? Or is this intentionally restricted by WebKit to fullscreen-only transitions?
Any pointers appreciated. Thanks!
I'm trying to download mods for Stardew Valley, before the beta it worked but now it doesn't. Is there anyone who can help to fix this? Used Firefox and Safari as well as Safari on my ipad.
Hi everyone, recently I used codex and GPT-5.2 to build a simple SSL certificate monitoring website, and I'd like to share some of my development experiences. The project link is at the end, but first, let's talk about the technical implementation.
The Motivation
I've encountered several service outages caused by expired SSL certificates in the past. Each time, I had to react after users reported the issue, which was very passive. While there are some monitoring tools on the market, they are either too heavy or lack the necessary features, so I decided to build my own.
Technology Stack
Next.js 16 + shadcn/ui + TypeScript
I chose Next.js because:
The development experience with App Router is excellent, with a clear mapping between routes and file structure.
Server Components reduce the need for client-side JavaScript.
Built-in features like image optimization and font loading are ready to use out of the box.
shadcn/ui is a component library based on Radix UI, and its advantages are:
Components are copied directly into your project, giving you full control.
It uses Tailwind CSS, making style customization easy.
It has excellent accessibility features.
Drizzle ORM + PostgreSQL
I've used Prisma before, but I tried Drizzle this time and found it to be more lightweight:
Faster type generation.
More intuitive SQL operations.
Better query performance.
better-auth Authentication System
This is a recent discovery I made, and it's more modern than NextAuth:
Better TypeScript support.
A cleaner API design.
Supports email/password and multiple OAuth providers (GitHub, Google).
Some Challenges I Faced
1. The Complexity of Certificate Chain Validation
At first, I thought checking an SSL certificate was simple—just get the certificate information. I later discovered that certificate chain validation is quite complex:
You need to verify the signature of each certificate in the chain.
You must check the integrity of the entire certificate chain.
You have to determine if the root certificate is trusted (which browsers have built-in lists for).
You need to handle cases where intermediate certificates are missing.
The solution was to create a complete certificate chain extraction and validation module that includes:
Extracting the full certificate chain from a TLS connection.
Verifying the signature and validity period of each certificate.
Detecting broken or incomplete chains.
Visualizing the chain structure in a tree format.
2. Designing the Security Scoring System
To help users quickly understand the security status of their certificates, I created a scoring system from A+ to F. The core logic is:
Weighted score across four dimensions
- Certificate Validity: 30%
- Chain Integrity: 25%
- Cryptographic Strength: 25%
- Protocol Version: 20%
If there are critical issues (e.g., expired certificate), the maximum grade is C
The challenges were:
How to allocate weights reasonably.
How to design the penalty rules.
How to provide valuable improvement suggestions.
Ultimately, I adopted a layered scoring approach where each dimension is calculated independently and then combined with weights.
3. Hydration Issues with Multi-language Routing
When supporting 6 languages, I encountered React Hydration errors:
// ❌ Incorrect approach
// app/[locale]/layout.tsx contained the <html> tag
// This conflicted with the root layout
// ✅ Correct approach
// The root layout has only one <html> tag
// Use a client component to dynamically update the lang attribute
4. Graceful Degradation for Redis Caching
To improve authentication performance, I added Redis caching. But I had to consider:
What happens when Redis is unavailable?
How do you handle cache and database data inconsistency?
The solution was:
Automatically fall back to the database if the Redis connection fails.
Actively invalidate the cache when the database is updated.
Provide cache statistics API to monitor the hit rate.
5. PageSpeed Optimization
Initially, the Lighthouse score was only in the 60s. The main problems were:
Large JavaScript Bundle
Used Next.js's dynamic imports to load components on demand.
Removed unused dependencies.
Enabled Tree Shaking.
Image Optimization
Used the Next.js Image component for automatic optimization.
Added appropriate placeholders.
Enabled lazy loading for images.
Font Loading
Used next/font for automatic font optimization.
Reduced the number of font variants.
Used font-display: swap to avoid layout shifts.
Critical Rendering Path
Identified critical CSS and inlined it into the HTML.
Deferred loading of non-critical JavaScript.
Optimized the loading order of third-party scripts.
Third-party Script Optimization
Deferred loading for Google Analytics, Crisp Chat, etc.
Used the defer/async attributes.
Considered using Web Workers for time-consuming tasks.
After optimization:
Performance: 60 → 95
Accessibility: 85 → 98
Best Practices: 90 → 100
SEO: 100
Some Technical Highlights
Certificate Chain Visualization
A tree structure is used to display the certificate chain, with expand/collapse functionality and color-coding for different statuses:
Green: Valid
Yellow: Expiring soon
Red: Expired
Security Issue Detection
Automatically detects insecure cryptographic algorithms:
MD5, SHA-1 signature algorithms.
Weak ciphers like RC4, DES.
Old protocols like TLS 1.0/1.1.
Multi-channel Notifications
Currently supports five notification channels: Email, Slack, Discord, Telegram, and Feishu. Users can freely combine them.
Project Link
https://guardssl.info
Features:
Free SSL certificate checking.
Domain monitoring and expiration reminders.
Security scoring and improvement suggestions.
Multi-language support (Chinese, English, Japanese, French, Spanish).
Feel free to try it out and provide feedback. We can discuss any questions you might have.
Hey everyone,
After installing iOS 26 beta, I started noticing unexpected behavior in our input event handlers.
Specifically, when users type into an field, event.target.value is always an empty string — but only when the JS file is loaded from a specific domain (e.g., t1.daumcdn.net). The exact same code works perfectly when hosted on other domains like t2.daumcdn.net or search1.daumcdn.net.
👉 I created a demo here:
🔗 https://codepen.io/bzasklcu-the-sans/pen/rNXogxL
The scripts loaded from each domain are 100% identical (apart from the top-level selector). Before iOS 26 beta, this worked fine.
I suspect this is related to ITP or some new cross-origin behavior in Safari, but I’d love to know if anyone else is running into this — or if someone knows a workaround.
Thanks!
Touch not working to close in-app close-ups since latest iOS 26 update
Topic:
Safari & Web
SubTopic:
General
How can I set it as a formal payment environment if I can make the payment now without any deduction?
Problem
Safari requires tabindex="0" for keyboard access to scrollable containers. Chrome (v130+) and Firefox (v4+) handle this automatically.
Current Behavior
Chrome/Firefox: Scrollable div with overflow: auto → automatically keyboard-accessible (Tab to focus, Arrow keys to scroll)
Safari: Same element → NOT keyboard-accessible unless:
Add tabindex="0", OR
Container has focusable children
Workaround
<div style="overflow-y: auto; height: 300px;" tabindex="0">
<!-- content -->
</div>
Issue: Adds unnecessary tab stops on Chrome/Firefox where not needed.
Request
Will Safari support auto-focus for scrollable containers? (matching Chrome/Firefox)
If not planned: Any official Apple guide for cross-browser scrollable accessibility?
Timeline? If on roadmap, estimated Safari version? Can I subscribe for updates?
Use Cases
Dropdown menus
Modal dialogs
Tab panels
Data tables
Chat interfaces
Reference:
WCAG 2.1 Keyboard Accessible: https://www.w3.org/WAI/WCAG21/Understanding/keyboard.html
Example component: https://www.radix-ui.com/themes/docs/components/scroll-area