I Built TGDown, a Chrome Extension for Downloading Telegram Web Media
I built TGDown, a Chrome extension that adds download controls for images and videos in Telegram Web. The original product goal was simple: when users browse a Telegram chat, channel, or search result, they should be able to save media without repeatedly opening the viewer, fighting the context menu, or handling every item one by one. The implementation was less simple. Telegram Web is a large, fast-moving single-page application. An extension needs to add UI without breaking scrolling, media interactions, theme behavior, or Telegram's own event handling. This post is about the architecture behind TGDown - and a dark-mode bug that forced me to rethink how its in-page UI was mounted. What TGDown does TGDown supports both Telegram Web interfaces: web.telegram.org/a/* web.telegram.org/k/* It provides: - One-click image and video downloads inside chats - Batch downloads from Telegram search results - A popup panel that lists detected media - Warnings for very large or long videos before a browser download starts - No separate TGDown account or subscription The extension architecture TGDown is a Manifest V3 extension built with TypeScript and Vue. There are three execution contexts involved: Content script Runs alongside Telegram Web, watches the DOM for supported images and videos, and mounts download controls.Page-context script Some downloads need Telegram Web's existing authenticated browser session. Since a content script is isolated from the page's JavaScript context, TGDown injects a small page-context script and communicates with it through DOM events.Extension pages The toolbar popup is a Vue application. It lists media detected while browsing and can trigger a download from the active Telegram tab. This separation keeps Telegram Web responsible for its own session, while the extension stays isolated from the application's internal code as much as possible. The dark-mode white-screen bug One of the most interesting bugs appeared only in Telegram's dark theme. My first approach for modal-style UI used a full-screen iframe . The iframe had a transparent background, which seemed like a safe way to isolate extension styles from Telegram's styles. In practice, it was not safe. On a dark Telegram page, users would occasionally see the entire page turn white. It looked as if Telegram had failed to load, but the problem was the extension UI. The sequence was roughly: - A full-screen iframe was inserted above Telegram. - The browser created the iframe document. - Before the iframe application had initialized - or when initialization failed - the iframe document rendered the browser's default page canvas. - That canvas was white, even though the iframe element itself was configured as transparent. - Because the iframe covered the viewport, it hid Telegram completely. The bug was much easier to notice in dark mode because a white flash or white overlay has maximum contrast against Telegram's dark UI. In light mode, the same failure could be almost invisible. The key lesson was simple: A transparent iframe element does not guarantee a transparent iframe document. The fix: Shadow DOM instead of a full-screen iframe I removed the full-screen iframe from the Telegram page UI path. TGDown now mounts its in-page controls in a Shadow DOM host. This preserves CSS isolation while avoiding a separate document with its own default rendering surface. The host is also designed not to interfere with Telegram: .tgdown-host { pointer-events: none; } .tgdown-host .download-button, .tgdown-host .modal, .tgdown-host .toast { pointer-events: auto; } The host itself ignores pointer events. Only actual TGDown controls opt back in, so Telegram remains clickable and scrollable everywhere else. Keeping the integration conservative Telegram Web has its own click handling, overlays, media viewer, and virtualized message list. A browser extension can easily become too aggressive: global CSS overrides, broad event listeners, or page-wide z-index layers may fix one download issue while breaking unrelated Telegram behavior. TGDown takes a narrower approach: - It only targets supported media elements and its own controls. - It avoids replacing Telegram's global objects or fetch implementation. - It waits until Telegram has completed its initial page load before injecting behavior that depends on the page context. - It uses Shadow DOM rather than global CSS to isolate extension UI. - It keeps the UI non-interactive by default, enabling pointer events only for visible TGDown controls. Telegram Web can still change its DOM structure, but keeping the integration narrow makes failures more contained and easier to diagnose. Browser downloads still have limits For regular images and videos, browser downloads work well. Larger media is different: browser memory, network stability, and the way Telegram Web exposes media URLs can affect reliability. TGDown warns before especially large or long downloads, but leaves the final decision to the user. Try TGDown If Telegram Web changes and TGDown stops detecting a specific kind of media, feedback is welcome. The most helpful report includes the Telegram Web version (A or K ), media type, and reproducible steps. Top comments (0)
Comments
No comments yet. Start the discussion.