diff --git a/public/miniapp/redirect.html b/public/miniapp/redirect.html
index b6e5151..cca3db1 100644
--- a/public/miniapp/redirect.html
+++ b/public/miniapp/redirect.html
@@ -148,14 +148,27 @@
const manualBtn = document.getElementById('manualBtn');
manualBtn.href = url;
- // Try to open the URL scheme directly
- // This page is opened in external browser, so custom schemes work
- window.location.href = url;
+ // Attempt to launch the app WITHOUT a top-level navigation. A direct
+ // `location.href = scheme` paints a full-page net::ERR_UNKNOWN_URL_SCHEME
+ // inside Android in-app browsers (Telegram/Yandex/…) and silently fails on
+ // iOS — hiding the manual button (Telegram bug #654272). A hidden iframe is
+ // contained: the app opens if installed, otherwise the failure stays inside
+ // the (invisible) frame and the button below stays usable.
+ try {
+ var frame = document.createElement('iframe');
+ frame.style.display = 'none';
+ frame.src = url;
+ document.body.appendChild(frame);
+ setTimeout(function() {
+ try { frame.parentNode.removeChild(frame); } catch (e) {}
+ }, 2000);
+ } catch (e) {
+ window.location.href = url;
+ }
- // Show manual button after a delay in case redirect didn't work
- setTimeout(function() {
- document.getElementById('errorBlock').classList.add('show');
- }, 2000);
+ // Programmatic opening is unreliable in in-app browsers, so surface the
+ // manual "Open app" button immediately — a user tap is the reliable trigger.
+ document.getElementById('errorBlock').classList.add('show');
})();