We're having trouble connecting to local area network websockets in Safari in the latest iOS26 Beta 3 (iPhone 14), both secure and unsecure. Code works < iOS26 & macOS, etc.
--
Unsecure behaviour: need to call connectWebSocket() twice, establishes connection reliably. Calling connectWebSocket() once, will sometimes work, sometimes not.
--
Secure behaviour: Error in debug console, even though the certificate has been accepted and the page is loaded as https. Error:
WebSocket connection to 'wss://192.168.1.81/api/webSocket' failed: The certificate for this server is invalid. You might be connecting to a server that is pretending to be “192.168.1.81”, which could put your confidential information at risk.
--
let apiEndpoint = window.location.hostname;
if (apiEndpoint == null || apiEndpoint == '') {
apiEndpoint = "192.168.1.81";
}
function connectWebSocket() {
if (webSocket && webSocket.readyState == 1) {
return;
}
if (webSocket) {
webSocket.close();
}
webSocket = new WebSocket(
(window.location.protocol === 'https:' ? "wss://" : "ws://") + apiEndpoint + "/api/webSocket",
);
webSocket.onerror = (error) => {
console.log("WebSocket error", error);
};
webSocket.onopen = () => {
console.log("WebSocket connected");
webSocket.send("volume");
webSocket.send("isPlaying");
};
webSocket.onmessage = (event) => {
const msg = event.data;
if (!msg) return;
if (msg.startsWith("volume")) {
const volume = parseInt(msg.replace('volume:',''));
const slider = document.getElementById("volumeSlider");
slider.value = volume;
slider.style.background = `linear-gradient(to right, #007bff ${volume}%, white ${volume}%)`;
} else if (msg.startsWith("isPlaying")) {
const url = msg.replace('isPlaying:', '');
let matchedEntry = null;
let coverToSelect = null;
categories.forEach((category, catIdx) => {
category.entries.forEach((entry, entryIdx) => {
if (entry.url === url) {
matchedEntry = entry;
coverToSelect = document.querySelector(`.cover[category-idx="${catIdx}"][entry-idx="${entryIdx}"]`);
}
});
});
if (matchedEntry && coverToSelect) {
selectCover(coverToSelect, true);
showNowPlayingBar(matchedEntry);
const top = coverToSelect.getBoundingClientRect().top + window.scrollY - 150;
window.scrollTo({ top, behavior: 'smooth' });
}
}
};
webSocket.onclose = () => {
console.log("WebSocket closed, retrying...");
setTimeout(connectWebSocket, 1000);
};
}
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible") {
connectWebSocket();
}
});
connectWebSocket();
Explore 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
Summary:
Content scripts injected via manifest continue to receive and respond to chrome.tabs.sendMessage() calls even after the user has navigated away from the original page, causing messages intended for the current tab to be handled by zombie contexts from previous pages.
Environment:
Safari/iOS Version: 18.5
Extension Manifest: Version 3
Expected Behavior:
When a user navigates from Page A to Page B:
Page A's content script context should be destroyed.
chrome.tabs.sendMessage(currentTabId, message) should only reach Page B's content script
Only Page B should be able to respond to action button clicks (or other background to content messages).
Actual Behavior:
When navigating from Page A to Page B:
Page A's content script context persists as a "zombie".
chrome.tabs.sendMessage(currentTabId, message) reaches zombie context instead of the Page B's one. Hence, it looks like the extension is broken because the content script does not respond to the background messages.
Details:
Tab ids are properly recognized by both background and content script
The problem does not always occur; it occurs on random occasions. It's quite easy to have it reproduced.
It can be reproduced easier if user clicks ext icon during site loading (before it fully loaded), triggering ActionClick (ext icon click) event and then sending a msg upon it to the content script
Regardless of whether the content script is injected into the tab using manifest.json, registerContentScripts, or executeScript, the problem is still there
Once the problem occurs, e.g. user is on macys.com but zombie injected content script believes it's google.com (a previous page), even refreshing the tab doesnt change anything - zombie context is still there (thinking it's still google.com) . Changing a domain to something completely different one could help though. Then going back to macys.com could still lead to the described issue.
A zombie content script does not have access to the page's console function and others.
Example communication
Sending following message from the background to the content script using chrome.tabs.sendMessage()
{
"tab": {
"id": 155,
"active": true,
"url": "https://www.macys.com/",
"title": "Macys.com"
}
}
Results in the content-script zombie context response (the url is taken from the window.location.href)
"message": {
"type": "ActionClicked",
"data": {}
},
"response": {
"data": {
"windowUrl": "https://www.google.com/",
"contentReached": true,
"timestamp": "1,753,138,945,272",
}
}
}
I'm testing web extension to safari on iOS. I've built and added extension application to simulator, but on safari settings shows no extensions.
I'm using Xcode 16.3 beta 2 with Simulator iOS 18.4 (22E5216h), tested on iPhone 16.
https://app.screencast.com/oUq4EMonmfT7u
https://app.screencast.com/MCquvHzmZi8QS
Adding Stack Trace for your reference:
thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1a6efe5b8)
frame #0: 0x00000001a6efe5b8 WebCoreWebCore::BaseAudioSharedUnit::BaseAudioSharedUnit() + 668 frame #1: 0x00000001a6efe044 WebCoreWebCore::CoreAudioSharedUnit::singleton() + 80
frame #2: 0x00000001a9521fe4 WebCoreWebCore::CoreAudioCaptureSource::create(WebCore::CaptureDevice const&, WebCore::MediaDeviceHashSalts&&, WebCore::MediaConstraints const*, std::__1::optional<WTF::ObjectIdentifierGeneric<WebCore::PageIdentifierType, WTF::ObjectIdentifierMainThreadAccessTraits<unsigned long long>, unsigned long long>>) + 360 frame #3: 0x00000001a94f180c WebCoreWebCore::RealtimeMediaSourceCenter::getUserMediaDevices(WebCore::MediaStreamRequest const&, WebCore::MediaDeviceHashSalts&&, WTF::Vector<WebCore::RealtimeMediaSourceCenter::DeviceInfo, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&, WTF::Vector<WebCore::RealtimeMediaSourceCenter::DeviceInfo, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&, WebCore::MediaConstraintType&) + 356
frame #4: 0x00000001a94f22cc WebCoreWebCore::RealtimeMediaSourceCenter::validateRequestConstraintsAfterEnumeration(WTF::Function<void (WTF::Vector<WebCore::CaptureDevice, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&&, WTF::Vector<WebCore::CaptureDevice, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&&)>&&, WTF::Function<void (WebCore::MediaConstraintType)>&&, WebCore::MediaStreamRequest const&, WebCore::MediaDeviceHashSalts&&) + 356 frame #5: 0x00000001a94fb394 WebCoreWTF::Detail::CallableWrapper<WebCore::RealtimeMediaSourceCenter::enumerateDevices(bool, bool, bool, bool, WTF::CompletionHandler<void ()>&&)::$_0, void>::~CallableWrapper() + 164
frame #6: 0x00000001a814bbe8 WebCoreWTF::Detail::CallableWrapper<WebCore::AVCaptureDeviceManager::refreshCaptureDevicesInternal(WTF::CompletionHandler<void ()>&&, WebCore::AVCaptureDeviceManager::ShouldSetUserPreferredCamera)::$_0::operator()()::'lambda'(), void>::call() + 520 frame #7: 0x00000001ab7f1aac JavaScriptCoreWTF::RunLoop::performWork() + 524
frame #8: 0x00000001ab7f1880 JavaScriptCoreWTF::RunLoop::performWork(void*) + 36 frame #9: 0x00000001935e7d0c CoreFoundationCFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 28
frame #10: 0x00000001935e7ca0 CoreFoundation__CFRunLoopDoSource0 + 172 frame #11: 0x00000001935e6a24 CoreFoundation__CFRunLoopDoSources0 + 232
frame #12: 0x00000001935e5c64 CoreFoundation__CFRunLoopRun + 840 frame #13: 0x000000019360a730 CoreFoundationCFRunLoopRunSpecific + 572
frame #14: 0x00000001e0fb5190 GraphicsServicesGSEventRunModal + 168 frame #15: 0x0000000196239f34 UIKitCore-[UIApplication _run] + 816
frame #16: 0x0000000196238164 UIKitCore`UIApplicationMain + 336
frame #17: 0x000000010811bec4 AppName.debug.dylibmain at AppDelegate.swift:25:13 frame #18: 0x00000001bae06a58 dyldstart + 5964
Hello Apple Developer Community,
I'm experiencing an issue with PDF link interaction in WKWebView that appears to be specific to iOS 26.
Problem Description:
I'm loading a PDF in WKWebView.The links may vary widely and are not necessarily DPF, so I need to load them using WKWebView. On iOS versions prior to 26, links within the PDF are clickable and work correctly. On iOS 26, the same links are not clickable (no response when tapped). Expected Behavior:
PDF links should remain clickable and functional across all iOS versions.
What I've Tried:
Tested opening the PDF directly in Safari on iOS 26 - links still not clickable This suggests the issue might be related to changes in the system's PDF rendering engine Reproduction Steps:
Load the PDF URL in WKWebView Navigate to page 12 Attempt to tap the link Environment:
Test Devices: iPhone 15(26.0 ) / iPhone 16 Pro Max(18.0.1 ) Xcode: 16.2
Questions:
Is this an intentional change in iOS 26's PDF handling or WKWebView? If so, is there a new API or configuration to restore link interactivity?
Any guidance or suggestions would be greatly appreciated!
Our team has implemented a video player using the HTML5 tag, but we have identified an issue with loading media files.
While Safari on iOS 18.0 downloads each TS file listed in the m3u8 playlist correctly, on iOS 18.4 and 18.5, a single TS file is downloaded repeatedly.
Our statistics indicate that approximately six requests are made per second for the same TS file.
Is this intended behavior?
If not, are there any known workaround or solutions?
If this issue is due to the OS or browser, are there any plans to address it in iOS 18.6 or a future release?
Could you advise on the proper channel to submit a bug report for this issue?
Similar issues have been reported in the past with WKWebView.
The previous thread is here:
https://developer.apple.com/forums/thread/784134
Topic:
Safari & Web
SubTopic:
General
I’m observing an intermittent issue with a Safari Web Extension on macOS 15.7 (Safari 26.0.1). After installing the Safari extension from the App Store, it appears under Settings → Extensions, but the enable checkbox is often missing.
Sometimes, after restarting Safari multiple times, the checkbox becomes visible. However, even when I manage to enable the extension, reopening Safari often hides the checkbox again.
However, I don't see this issue in safari 26 with macOS 26
I’d like to know if this behavior is a known issue with Safari 26 or macOS 15.7?
Any workaround available?
I'm a web developer of WebRTC based web app for video and audio calls. After updating to iOS 26.1 beta I noticed, that my app can't use microphone anymore.
When I'm calling to getUserMedia with audio set to true, Safari returns error "No AVAudioSessionCaptureDevice device".
Other WebRTC demo apps also can't access microphone on this firmware.
And maybe it's connected somehow, but safari can't detect connected AirPods Pro 2 as an input device.
So, this bug brakes any WebRTC app, that uses microphones.
The issue of fixed elements with
{ bottom: 0 }
moving up when scrolling still persists.
It seems to be a general issue with the IOS 26 release.
It affects other browser too. I tested on browsers such as Safari, Chrome, Firefox, Edge and Bravo.
With the exception of Edge, all the others display the behavior.
Device: iPhone 15 Pro
IOS Version: 26.0.1
hi
Testing on OS26 Public Beta 6.
In Safari, if you enter x homepage and scroll, the tab bar sticks to the bottom and moves.
Make the keyboard appear in the search window
When scrolling down on the Safari homepage again, the issue of not being able to stick to the bottom appears.
Is it because the liquid glass UI was applied this time? and safari bug?
Please let me know if I'm missing anything
Topic:
Safari & Web
SubTopic:
General
Device: iPhone 15pro, ios26.0 (23A 341)
IOS version: 26.0 (23A 341)
When using position: sticky; bottom: 0, the div is expected to stick to the bottom of the viewport when the browser toolbar hides while scrolling. However, it stops at the height where the toolbar was, instead of moving down with the disappearing toolbar.
In the image below, the red-bordered navigation shows the situation where it does not stick to the bottom.
i
I want to print the content of a WKWebView. I've done some searching, and many people have struggled with this over the years. Some claimed success, but their solutions don't work for me. One person created images for each pages and printed that, but then if you were to print to PDF, you'd get a PDF containing images rather than text.
If I just call the printView(_:)) method of the view, I get blank pages.
With the following more elaborate code, I get a partial printout, 11 out of what should be about 13 pages.
let info = NSPrintInfo.shared
info.topMargin = 72.0;
info.bottomMargin = 72.0;
info.leftMargin = 72.0;
info.rightMargin = 72.0;
info.isVerticallyCentered = false;
info.isHorizontallyCentered = false;
info.horizontalPagination = .fit;
info.verticalPagination = .automatic;
let printOp = webView!.printOperation( with: info )
printOp.canSpawnSeparateThread = true
printOp.view?.frame = NSMakeRect( 0, 0,
info.paperSize.width, info.paperSize.height )
printOp.runModal(for: webView.window!, delegate: self,
didRun: nil, contextInfo: nil )
When I run the above under the debugger, I see console messages saying
CGContextClipToRect: invalid context 0x0.
Once the print dialog appears, if I touch (but not change) the selected printer, then the page count changes to the correct value.
Hi all,
With version 18.4 beta, I have a problem with the display of webviews in the app. In particular, the app of my bank has webviews inside it, and as they are not loading, I am unable to access it. Can you help me? Thank you.
Our app encountered a new crash since beta5(23A5308g) released last week,and it seems the crash is not solved yet in beta6(23A5318c).The crash stack below
`-[UIView _backing_setPosition:]
-[UIView setCenter:]
-[_UIEditMenuContentPresentation _displayPreparedMenu:titleView:reason:didDismissMenu:configuration:]
___54-[_UIEditMenuContentPresentation _displayMenu:reason:]_block_invoke
-[UIEditMenuInteraction _editMenuPresentation:preparedMenuForDisplay:completion:]
-[_UIEditMenuContentPresentation _displayMenu:reason:]
-[_UIEditMenuContentPresentation displayMenu:configuration:]
___58-[UIEditMenuInteraction presentEditMenuWithConfiguration:]_block_invoke
___80-[UIEditMenuInteraction _prepareMenuAtLocation:configuration:completionHandler:]_block_invoke
___109-[UITextContextMenuInteraction _editMenuInteraction:menuForConfiguration:suggestedActions:completionHandler:]_block_invoke
___107-[UITextContextMenuInteraction _querySelectionCommandsForConfiguration:suggestedActions:completionHandler:]_block_invoke
WTF::CompletionHandler<void (WebKit::DocumentEditingContext&&)>::operator()(WebKit::DocumentEditingContext&&)
WTF::Detail::CallableWrapper<IPC::Connection::makeAsyncReplyCompletionHandler<Messages::WebPage::RequestDocumentEditingContext, WTF::CompletionHandler<void (WebKit::DocumentEditingContext&&)> >(WTF::CompletionHandler<void (WebKit::DocumentEditingContext&&)>&&, WTF::ThreadLikeAssertion)::{lambda(IPC::Connection*, IPC::Decoder*)#1}, void, IPC::Connection*, IPC::Decoder*>::call(IPC::Connection*, IPC::Decoder*)
WTF::Detail::CallableWrapper<WebKit::AuxiliaryProcessProxy::sendMessage(WTF::UniqueRefIPC::Encoder&&, WTF::OptionSetIPC::SendOption, std::__1::optionalIPC::ConnectionAsyncReplyHandler, WebKit::AuxiliaryProcessProxy::ShouldStartProcessThrottlerActivity)::$_1, void, IPC::Connection*, IPC::Decoder*>::call(IPC::Connection*, IPC::Decoder*)
IPC::Connection::dispatchMessage(WTF::UniqueRefIPC::Decoder)
IPC::Connection::dispatchIncomingMessages()
WTF::RunLoop::performWork()
WTF::RunLoop::performWork(void*)
_CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION
___CFRunLoopDoSource0
___CFRunLoopDoSources0
___CFRunLoopRun
__CFRunLoopRunSpecificWithOptions
_GSEventRunModal
-[UIApplication _run]
_UIApplicationMain
main main.m
start
We’re currently working on an OTT-based application where we integrate Google Ad Manager to serve video ads. As part of the ad experience, users often see a “Learn More” CTA (Call to Action) on these ads.
As per our current requirement, when a user taps “Learn More” on an ad:
• The link should open in Safari (i.e., an external browser) on iOS devices
• The Safari browser should ideally open in portrait orientation, as the ad content and layout are optimised for portrait mode
However, based on our understanding and technical constraints on iOS, it appears that:
• Orientation control is restricted to the app’s own context.
• Once Safari is launched via UIApplication.shared.open, we no longer have control over how it behaves in terms of orientation.
• iOS system behaviour determines Safari’s orientation based on the device’s physical orientation and Safari’s own internal configuration.
Could you please confirm if there’s any supported way (via SDK, deep link config, or otherwise) to enforce portrait orientation in Safari when opening such external URLs from within an iOS app?
If this is not technically feasible, we would appreciate any best practices or alternatives you can suggest for ensuring a consistent user experience.
Topic:
Safari & Web
SubTopic:
General
After upgrading to Safari version 18, we encountered an issue with my extension’s background script not being able to access cookies. Previously, in Safari versions 17 and below, the extension worked as expected. Now, when the extension tries to retrieve cookies using browser.cookies.getAll(), it returns an empty list. However, if we open the extension’s developer tools, the cookies are visible and accessible.
It seems that Safari only provides cookie data after the developer tools have been opened. However, after relaunching Safari and launching the extension without opening the developer tools, browser.cookies.getAll() still returns an empty list.
Has anyone else experienced this?
STEPS TO REPRODUCE
Download this minimal app : https://www.icloud.com/iclouddrive/0bajlhnuQaG6T5NsFKXEB0U9Q#test%5Fcookies
Compile test_mv2 extension (in test_cookies.getAll.zip).
Launch test_mv2.app and activate extension.
Click on the extension's button (browserAction).
Open the developer tools.
Observe an empty list of cookies.
Click on the extension's button (browserAction).
Cookies are retrieved as expected.
iOS Safari 18.4/18.5 with IIS Windows Authentication with negotiate hangs after entering credentials
I don't think the issue is specific iOS 18.
We have a web application that runs with IIS Authentication of Windows and Anonymous. Initially the app opens and the user clicks a button and triggers the "401 Challenge" via ASP.NET. The browser presents the Active Directory login, user enters credentials, clicks Sign In, and the browser hangs (may actually be negotiating something). After a few minutes the user is logged into the application.
We have done a number of google searches/AI to try to determine what to change and there is no clear solution. Is there anything else to try?
This problem is not seen in Chrome on iOS or on a Windows machine. Strangely it is also not seen using BrowserStack with one of their "real" devices.
We have other apps that run with just Windows Authorization and this problem is not observed.
Topic:
Safari & Web
SubTopic:
General
When CHIPS was introduced in 18.4 it worked well, however on 18.5 it does not appear to work. There do not appear to be release notes about this in 18.5, so can someone provide definitive if this is a defect that will be fixed, or have they already been deprecated?
I am creating a Safari Web Extension.
There are two calls let say, call1 and call2 which gets executed in sequence by browser, call1 gives a 302 type response and redirects to call2.
When creating DNR rule for adding "Cookie" in the request header of call1, the same cookie gets added to the request header of call2 as well(Same is the case for other headers/custom headers as-well). Because of this the set-cookie present in response header of call1 is not sent in the request header of call2, and returns 400 response.
The same setting is working fine for other browsers chrome & firefox.
Is this a bug or DNR works differently for safari ?
currently "webRequestBlocking" works in safari for manifest v3, is there any development of it getting removed just like it's removed in chrome in mv3.
This is my first post, so please forgive me if it is to the wrong area.
I've been using Tahoe for a few days and, overall, it's very stable. But the one thing that has bothered me to no end is Safari's new behavior with respect to its header (Address bar, Favorite bookmarks bar, tab bar) background color. The web content of the active tab seems to affect everything - and oftentimes makes things completely unreadable - at least in "Dark" mode. For instance, if a web page uses a white background, the Favorites bookmark labels are the same color as the bookmark background, so reading the labels is simply impossible. At other times, they're just very difficult to read.
Similarly, it is almost always impossible to tell which tab is the active one - my only workaround is to try 100% brightness....or to just guess.
When Apple previously experimented with letting content bleed through to the top, there was a setting for stopping it - but I don't see such a setting anymore. Do you you know of any way to stop this effect?